Advanced Place Details コンポーネント
Place Details コンポーネントの Advanced バージョンは、Places Details Essentials と同じ機能を提供します。また、ビジネス名を表示するかどうかを選択したり、コンポーネントのアクション ボタンを設定したり、表示されるクチコミやメディアに検索とフィルタリングのオプションを適用したりすることもできます。
高度な Place Details の構成
上級者向け機能にアクセスするには、AdvancedPlaceDetailsView または AdvancedPlaceDetailsCompactView を使用します。
コンテンツの表示オプション
AdvancedPlaceDetailsContent の列挙型を使用して、表示するコンテンツを指定できます。プレイスの詳細の基本と同じコンテンツをすべて設定できるほか、プレイス名を表示するかどうかを選択できます。
アクション ボタンを設定する
AdvancedPlaceDetailsView または AdvancedPlaceDetailsCompactView の .cornerActions メソッドと .mainActions メソッドを使用して、アクション ボタンを削除またはカスタマイズします。
視覚的な表示ルールの要件
重要: カスタム操作ボタンが Google 以外の第三者とユーザー情報を共有する場合、エンドユーザーにそのことを明確に伝える必要があります。ビジュアル アトリビューションの要件をご覧ください。
右の例は、ユーザー情報が「Altostrat」に送信されることを明確にするカスタム画像を示しています。
検索とフィルタのオプションを適用する
AdvancedPlaceDetailsView または AdvancedPlaceDetailsCompactView の .searchMediaOptions メソッドと .searchReviewOptions メソッドを使用して、メディアまたはレビューの検索とフィルタリングを有効にします。
カスタム コンテンツ スロットを作成する
カスタム コンテンツ スロットを使用すると、独自のコンテンツ(AI 生成の要約、旅程のタイムスタンプ、カスタム バッジなど)を事前定義されたレイアウト ゾーンに直接追加できます。
カスタム コンテンツを追加するには、AdvancedPlaceDetailsCompactView の .placeDetailsCompactContentSlot メソッドを使用します。使用できる位置は .basicSectionTop と .basicSectionBottom です。
コンテンツ スロットの帰属表示の要件とコンテンツの提案
カスタム コンテンツ スロットがマウントされると、開示情報が自動的に更新され、どのコンテンツが Google によって提供され、どのコンテンツがサードパーティによって提供されるかが明確になります。
すべきこと
Google のプレイスの詳細とカスタム コンテンツの間に明確な視覚的階層を維持し、情報のソースに関する曖昧さを防ぎます。
すべきこと
ユーザーの直近の目標に合わせてローカライズされた、価値の高い分析情報を検討します。リアルタイムの予約ウィンドウや現在の空き状況などのカスタマイズされたコンテンツは、ユーザーがより迅速かつ十分な情報に基づいて判断を下すのに役立ちます。
悪い例
Google 提供のコンテンツを非表示にした場合でも、評価、レビュー、営業時間など、既存の Google プレイスの詳細情報を複製しないでください。そうすると、コンテンツのソースや、Google から提供されたものか第三者から提供されたものかについて、ユーザーが混乱する可能性があります。
悪い例
Google の公式な推奨と誤解される可能性のある、帰属先のない主張やバッジ(「おすすめ!」など)を表示しないでください。カスタム コンテンツでは、出典を明示的に明記する必要があります。
悪い例
カスタムのプレース コンテナ内に広告、マーケティング コピー、プロモーション割引、定期購入のプロンプトを含めないでください。
高度な Place Details の例
場所の名前を省略する
地名を除外するには、AdvancedPlaceDetailsConfiguration の content パラメータに .name を含めないでください。Swift
struct DemoView: View { static let peetsCoffeePlaceID = "ChIJT7FdmYiAhYAROFOvrIxRJDU" // Query for loading the place details component. @State var query: PlaceDetailsQuery = PlaceDetailsQuery( identifier: .placeID(peetsCoffeePlaceID) ) @State private var favoritePlaces: Set<String> = [] var body: some View { AdvancedPlaceDetailsView( query: $query, configuration: AdvancedPlaceDetailsConfiguration( content:[.address()], theme: PlacesMaterialTheme() ), placeDetailsCallback: { result in if let place = result.place { print("Place: \(place.description)") } else { print("Error: \(String(describing: result.error))") } } ) } }
操作ボタンを削除する
Swift
struct DemoView: View { static let peetsCoffeePlaceID = "ChIJT7FdmYiAhYAROFOvrIxRJDU" @State var query: PlaceDetailsQuery = PlaceDetailsQuery( identifier: .placeID(peetsCoffeePlaceID) ) var body: some View { AdvancedPlaceDetailsView( query: $query, configuration: AdvancedPlaceDetailsConfiguration( content: AdvancedPlaceDetailsView.allContent, theme: PlacesMaterialTheme() ), placeDetailsCallback: { result in if let place = result.place { print("Place: \(place.description)") } else { print("Error: \(String(describing: result.error))") } } ) .mainActions{ _ in return [] } } }
カスタム アクションと事前定義アクションを追加する
このサンプルでは、ユーザーが場所をお気に入りに追加またはお気に入りから削除するためのオプションと、事前定義された [地図で開く] アクションを追加します。
Swift
struct DemoView: View { static let peetsCoffeePlaceID = "ChIJT7FdmYiAhYAROFOvrIxRJDU" @State var query: PlaceDetailsQuery = PlaceDetailsQuery( identifier: .placeID(peetsCoffeePlaceID) ) @State var favoritePlaces: Set<String> = [] var body: some View { AdvancedPlaceDetailsView( query: $query, configuration: AdvancedPlaceDetailsConfiguration( content: AdvancedPlaceDetailsView.allContent, theme: PlacesMaterialTheme() ), placeDetailsCallback: { result in if let place = result.place { print("Place: \(place.description)") } else { print("Error: \(String(describing: result.error))") } } ) .mainActions{ place in var actions: [MainPlaceActionElement] = [] let placeID = place.placeID! if self.favoritePlaces.contains(placeID) { actions.append( .action( MainPlaceAction( image: Image(systemName: "heart.fill"), label: "Unfavorite" ) { _ in self.toggleFavorite(placeID) } ) ) } else { actions.append( .action( MainPlaceAction( image: Image(systemName: "heart"), label: "Favorite" ) { _ in self.toggleFavorite(placeID) } ) ) } actions.append(.actionId(.openMap(style: .primary))) return actions } .cornerActions { place in var actions: [CornerPlaceActionElement] = [] let placeID = place.placeID! if self.favoritePlaces.contains(placeID) { actions.append( .action( CornerPlaceAction( image: Image(systemName: "heart.fill"), accessibilityLabel: "Unfavorite", ) { _ in self.toggleFavorite(placeID) } ) ) } else { actions.append( .action( CornerPlaceAction( image: Image(systemName: "heart"), accessibilityLabel: "Favorite", ) { _ in self.toggleFavorite(placeID) } ) ) } actions.append(.actionId(.openMap(style: .primary))) return actions } } func toggleFavorite(_ placeID: String) { if favoritePlaces.contains(placeID) { favoritePlaces.remove(placeID) } else { favoritePlaces.insert(placeID) } } }
クチコミとメディアをフィルタする
このコードサンプルは、「コーヒー」に言及しているメディアとレビューのみを表示します。
Swift
struct DemoView: View { static let peetsCoffeePlaceID = "ChIJT7FdmYiAhYAROFOvrIxRJDU" @State var query: PlaceDetailsQuery = PlaceDetailsQuery( identifier: .placeID(peetsCoffeePlaceID) ) let searchMediaOptions = SearchMediaOptions(query: "coffee") let searchReviewsOptions = SearchReviewsOptions(query: "coffee") var body: some View { AdvancedPlaceDetailsView( query: $query, configuration: AdvancedPlaceDetailsConfiguration( content: [.media(), .reviews()], theme: PlacesMaterialTheme() ), placeDetailsCallback: { _ in } ) .searchMediaOptions(searchMediaOptions) { results in guard let result = results.first else { return } switch result { case .success(let summary): print("Summary: \(summary)") case .failure(let error): print("Error: \(error)") } } .searchReviewsOptions(searchReviewsOptions) { results in guard let result = results.first else { return } switch result { case .success(let summary): print("Summary: \(summary)") case .failure(let error): print("Error: \(error)") } } } }
コンテンツ スロットを作成する
このサンプルでは、basicSectionTop スロットと basicSectionBottom スロットにコンテンツを追加します。
Swift
import SwiftUI import PlacesSwift struct ItineraryCard: View { static let peetsCoffeePlaceID = "ChIJT7FdmYiAhYAROFOvrIxRJDU" @State var query: PlaceDetailsQuery = PlaceDetailsQuery( identifier: .placeID(peetsCoffeePlaceID) ) var body: some View { AdvancedPlaceDetailsCompactView( orientation: .vertical, query: $query, configuration: AdvancedPlaceDetailsCompactConfiguration( content: AdvancedPlaceDetailsCompactView.allContent, theme: PlacesMaterialTheme() ), placeDetailsCallback: { _ in } ) .placeDetailsCompactContentSlot(position: .basicSectionTop) { place in Text("Day 2 • 2:30 PM") .font(.caption) .fontWeight(.bold) .foregroundColor(.accentColor) } .placeDetailsCompactContentSlot(position: .basicSectionBottom) { place in VStack(alignment: .leading, spacing: 4) { Text("AI Notes") .font(.caption) .bold() Text("Great quiet atmosphere for morning meetings. Famous for house-roasted pour-overs.") .font(.footnote) .foregroundColor(.secondary) } .padding(8) .background(Color(.systemGray6)) .cornerRadius(8) } } }