Componente Place Details avanzato

La versione Advanced del componente Place Details offre le stesse funzionalità di Places Details Essentials. Inoltre, ti consente 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 i contenuti da visualizzare utilizzando gli enum in AdvancedPlaceDetailsContent. Puoi configurare tutti i contenuti di Places Details Essentials e scegliere se visualizzare il nome del luogo.

Configura 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 di Place Details avanzato con pulsante personalizzato

Importante: devi chiarire agli utenti finali quando un pulsante di azione personalizzata condividerà le informazioni 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".

Applica le opzioni di ricerca e filtro

Utilizza i metodi .searchMediaOptions e .searchReviewOptions di AdvancedPlaceDetailsView o AdvancedPlaceDetailsCompactView per attivare la ricerca e l'applicazione di filtri per contenuti multimediali o recensioni.

Crea aree contenuti personalizzate

Opzioni di posizionamento degli slot per contenuti personalizzati

Gli slot per contenuti personalizzati ti consentono di aggiungere i tuoi contenuti (come riepiloghi generati dall'AI, timestamp degli itinerari o badge personalizzati) direttamente in 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 gli slot di contenuti

Quando viene montato un area contenuti personalizzata, l'informativa si aggiorna automaticamente per chiarire quali contenuti sono forniti da Google e che alcuni contenuti sono forniti da terze parti.

Cosa fare

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

Evitare ambiguità sulla fonte delle informazioni

Cosa fare

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

Fornire insight di alto valore

Cosa non fare

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

Non duplicare i dettagli di un luogo Google esistente

Cosa non fare

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

Non mostrare affermazioni o badge non attribuiti

Cosa non fare

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

Non includere annunci, testi di marketing, sconti promozionali o richieste di abbonamento

Esempi di Place Details (Advanced)

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

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

Aggiungi azioni personalizzate e predefinite

Questo esempio aggiunge un'opzione che consente a un utente di aggiungere o rimuovere un luogo dai preferiti, oltre 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)
    }
  }
}

Filtra recensioni e contenuti multimediali

Questo esempio di codice mostra solo i contenuti multimediali e le 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)")
      }
    }
  }
}

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