Componente Advanced Place Details

La versione avanzata del componente Place Details offre le stesse funzionalità di Places Details Essentials. Consente inoltre di scegliere se visualizzare il nome del luogo, configurare i pulsanti di azione del componente e applicare opzioni di ricerca e filtro alle recensioni e ai contenuti multimediali visualizzati.

Configurazione avanzata di Place Details

Utilizza AdvancedPlaceDetailsView o AdvancedPlaceDetailsCompactView per accedere alle funzionalità avanzate.

Opzioni di visualizzazione dei contenuti

Puoi specificare quali contenuti visualizzare utilizzando le enumerazioni in AdvancedPlaceDetailsContent. Puoi configurare tutti gli stessi contenuti di Places Details Essentials, nonché scegliere se visualizzare il nome del luogo.

Configurare i pulsanti di azione

Utilizza i metodi .cornerActions e .mainActions di AdvancedPlaceDetailsView o AdvancedPlaceDetailsCompactView per rimuovere o personalizzare i pulsanti di azione.

Requisiti di attribuzione visiva

Visualizzazione compatta dei dettagli del luogo con pulsanti personalizzati
Visualizzazione compatta dei dettagli avanzati del luogo con pulsante personalizzato

Importante:devi comunicare chiaramente agli utenti finali quando un pulsante di azione personalizzata condividerà le informazioni dell'utente con una terza parte diversa da Google. Consulta i requisiti di attribuzione visiva.

L'esempio a destra mostra un'immagine personalizzata che indica chiaramente che le informazioni dell'utente verranno inviate ad "Altostrat".

Applicare le opzioni di ricerca e filtro

Utilizza i metodi .searchMediaOptions e .searchReviewOptions di AdvancedPlaceDetailsView o AdvancedPlaceDetailsCompactView per attivare la ricerca e il filtro per contenuti multimediali o recensioni.

Creare slot di contenuti personalizzati

Opzioni di posizionamento degli slot di contenuti personalizzati

Gli spazi per i contenuti personalizzati ti consentono di aggiungere i tuoi contenuti (ad esempio riepiloghi generati dall'AI, timestamp dell'itinerario o badge personalizzati) direttamente nelle zone di layout predefinite.

Per aggiungere contenuti personalizzati, utilizza il metodo .placeDetailsCompactContentSlot di AdvancedPlaceDetailsCompactView. Le posizioni disponibili sono .basicSectionTop e .basicSectionBottom.

Requisiti di attribuzione e suggerimenti per i contenuti degli spazi pubblicitari

Quando viene montato uno spazio per i contenuti personalizzati, l'informativa si aggiorna automaticamente per chiarire quali contenuti sono forniti da Google e quali da terze parti.

Cosa fare

Mantieni una gerarchia visiva chiara tra i dettagli di Google Place e i contenuti personalizzati per evitare ambiguità sull'origine delle informazioni.

Evitare ambiguità sull'origine delle informazioni

Cosa fare

Prendi in considerazione approfondimenti localizzati e di alto valore personalizzati in base agli obiettivi immediati degli utenti. Contenuti personalizzati come finestre di prenotazione in tempo reale o disponibilità attuale aiutano gli utenti a prendere decisioni più rapide e informate.

Fornire approfondimenti di alto valore

Cosa non fare

Non duplicare i dettagli esistenti di Google Places, come valutazioni, recensioni o orari di apertura, anche se hai nascosto i contenuti forniti da Google. In questo modo, gli utenti potrebbero non capire la fonte dei contenuti e se provengono da Google o da una terza parte.

Non duplicare i dettagli di Google Places esistenti

Cosa non fare

Non mostrare affermazioni o badge non attribuiti (ad esempio "Consiglio migliore") che potrebbero essere scambiati per approvazioni ufficiali di Google. I contenuti personalizzati devono attribuire esplicitamente la fonte.

Non mostrare badge o affermazioni non attribuite

Cosa non fare

Non includere annunci, testi di marketing, sconti promozionali o inviti all'abbonamento all'interno dei contenitori di luoghi personalizzati.

Non includere annunci, testi di marketing, sconti promozionali o inviti all'abbonamento

Esempi di Place Details avanzati

Omettere il nome del luogo

Per omettere il nome del luogo, non includere .name nel parametro content di AdvancedPlaceDetailsConfiguration.

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))")
        }
      }
    )
  }
}

Rimuovere i pulsanti di azione

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 []
    }
  }
}

Aggiungere azioni personalizzate e predefinite

Questo esempio aggiunge un'opzione per consentire a un utente di aggiungere o rimuovere un luogo dai preferiti, insieme all'azione predefinita Apri in Maps.

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)
    }
  }
}

Filtrare recensioni e contenuti multimediali

Questo esempio di codice mostra solo contenuti multimediali e recensioni che menzionano "caffè".

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)")
      }
    }
  }
}

Creare spazi per i contenuti

Questo esempio aggiunge contenuti agli slot basicSectionTop e 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)
      }
    }
}