Componente Advanced Place Details
La versión Advanced del componente Place Details ofrece las mismas funciones que Place 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 y elegir si se muestra el nombre del lugar.
Cómo configurar 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 cuando un botón de acción personalizada comparta información del usuario con un tercero que no sea Google. Consulta los requisitos de atribución visual.
En el ejemplo de la derecha, se muestra una imagen personalizada que deja en claro que la información del usuario se enviará a "Altostrat".
Aplicar 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 de opiniones.
Crea espacios de contenido personalizados
Los espacios de contenido personalizado te permiten agregar tu propio contenido (como resúmenes generados por IA, marcas de tiempo de itinerarios o insignias personalizadas) directamente en zonas de diseño predefinidas.
Para agregar 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 los 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 proporcionar estadísticas localizadas y de gran valor adaptadas 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 Place, 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 afirmaciones ni insignias sin atribución (por ejemplo, "¡La mejor recomendación!") que puedan confundirse con respaldos 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))") } } ) } }
Quita 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 un usuario marque o quite de favoritos un lugar, 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 incluyen fotos, videos y opiniones que mencionan "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) } } }