Componente Advanced Place Details
La versión avanzada del componente Place Details ofrece las mismas funciones que Places Details Essentials. También te permite elegir si se muestra el nombre del lugar, configurar los botones de acción del componente y aplicar opciones de búsqueda y filtrado a las opiniones y el contenido multimedia que se muestran.
Configuración avanzada de Place Details
Usa AdvancedPlaceDetailsView o AdvancedPlaceDetailsCompactView para acceder a las funciones avanzadas.
Opciones de visualización de contenido
Puedes especificar qué contenido mostrar con las enumeraciones en AdvancedPlaceDetailsContent. Puedes configurar todo el contenido de Places Details Essentials, así como elegir si se muestra el nombre del lugar.
Configura los botones de acción
Usa los métodos .cornerActions y .mainActions de AdvancedPlaceDetailsView o AdvancedPlaceDetailsCompactView para quitar o personalizar los botones de acción.
Requisitos de atribución visual
Importante: Debes dejar en claro a los usuarios finales cuándo un botón de acción personalizado compartirá información del usuario con un tercero que no sea Google. Consulta los requisitos de atribución visual.
El ejemplo de la derecha muestra una imagen personalizada que deja en claro que la información del usuario se enviará a "Altostrat".
Aplica opciones de búsqueda y filtrado
Usa los métodos .searchMediaOptions y .searchReviewOptions de AdvancedPlaceDetailsView o AdvancedPlaceDetailsCompactView para habilitar la búsqueda y el filtrado de contenido multimedia o opiniones.
Crea espacios de contenido personalizados
Las ranuras de contenido personalizadas te permiten agregar tu propio contenido (como resúmenes generados por IA, marcas de tiempo de itinerarios o insignias personalizadas) directamente en las zonas de diseño predefinidas.
Para agregar objetos de contenido personalizado, usa el método .placeDetailsCompactContentSlot de AdvancedPlaceDetailsCompactView. Las posiciones disponibles son .basicSectionTop y .basicSectionBottom.
Requisitos de atribución y sugerencias de contenido para espacios de contenido
Cuando se activa un espacio de contenido personalizado, la divulgación se actualiza automáticamente para aclarar qué contenido proporciona Google y qué contenido proporcionan terceros.
Qué debes hacer
Mantén una jerarquía visual clara entre los detalles de Google Place y el contenido personalizado para evitar cualquier ambigüedad sobre la fuente de la información.
Qué debes hacer
Considera las estadísticas localizadas y valiosas que se adapten a los objetivos inmediatos de tus usuarios. El contenido personalizado, como los períodos de reserva en tiempo real o la disponibilidad actual, ayuda a los usuarios a tomar decisiones más rápidas y fundamentadas.
Qué no debes hacer
No dupliques los detalles existentes de Google Places, como las calificaciones, las opiniones o el horario de atención, incluso si ocultaste el contenido proporcionado por Google. Si lo haces, los usuarios podrían confundirse sobre la fuente del contenido y si proviene de Google o de un tercero.
Qué no debes hacer
No muestres insignias ni afirmaciones sin atribución (por ejemplo, "¡Recomendación principal!") que se puedan confundir con recomendaciones oficiales de Google. El contenido personalizado debe atribuir explícitamente su fuente.
Qué no debes hacer
No incluyas anuncios, textos de marketing, descuentos promocionales ni mensajes de suscripción en los contenedores de lugares personalizados.
Ejemplos avanzados de Place Details
Omitir el nombre del lugar
Para omitir el nombre del lugar, no incluyas.name en el parámetro content de 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))") } } ) } }
Cómo quitar los botones de acción
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 [] } } }
Agrega acciones personalizadas y predefinidas
En este ejemplo, se agrega una opción para que el usuario marque un lugar como favorito o deje de marcarlo, junto con la acción predefinida Abrir en 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) } } }
Cómo filtrar opiniones y contenido multimedia
En esta muestra de código, solo se muestran los medios y las opiniones que mencionan la palabra "café".
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)") } } } }
Cómo crear espacios de contenido
En este ejemplo, se agrega contenido a los espacios basicSectionTop y 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) } } }