Componente Advanced Place Details
La versione avanzata del componente Place Details offre le stesse funzionalità di Places Details Essentials. Consente inoltre di configurare i pulsanti di azione del componente e di applicare opzioni di ricerca e filtro alle recensioni e ai contenuti multimediali visualizzati.
Supporto integrato di Jetpack Compose
Places UI Kit fornisce funzioni @Composable Jetpack Compose per AdvancedPlaceDetailsCompact. Questi composable utilizzano lo stato sollevato, il supporto dei modificatori integrati e i DSL di slot nativi di Compose.
Il seguente esempio di codice mostra come utilizzare la funzione componibile per un layout verticale.
Kotlin
import android.util.Log import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.unit.dp import com.google.android.libraries.places.api.model.Place import com.google.android.libraries.places.compose.AdvancedPlaceDetailsCompact import com.google.android.libraries.places.compose.PlaceReference import com.google.android.libraries.places.compose.action.CornerAction import com.google.android.libraries.places.compose.action.MainAction import com.google.android.libraries.places.compose.Orientation @Composable fun SampleAdvancedPlaceDetailsCompactCard( placeId: String, bookmarkIcon: Painter, onSavePlaceClicked: (Place) -> Unit ) { AdvancedPlaceDetailsCompact( // defines the place to be displayed reference = PlaceReference.PlaceId(placeId), // defines the orientation orientation = Orientation.VERTICAL, // defines custom styling modifier = Modifier .fillMaxWidth() .padding(16.dp), preferTruncation = true, enableLightbox = true, mainActions = { place -> listOf( MainAction.OpenDirections(), MainAction.OpenWebsite(), MainAction.Call() ) }, // action button configuration cornerActions = { place -> listOf( CornerAction.Custom( icon = bookmarkIcon, text = "Save Place", onClick = { onSavePlaceClicked(place) } ) ) }, onPlaceLoaded = { place -> Log.d("Places", "Successfully loaded place: ${place.id}") }, onPlaceLoadFailed = { exception -> Log.e("Places", "Failed to load place", exception) } ) { // --- Slot: Injected directly above the place name --- basicSectionTop { Text( text = "Featured in 'Top 10 Coffee Shops in SF'", style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.secondary, modifier = Modifier.padding(top = 4.dp, bottom = 2.dp) ) } // --- Slot: Injected directly below the action buttons --- basicSectionBottom { Text( text = "Notes: Great quiet atmosphere for meetings.", style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant ) } } }
Configurazione avanzata di Place Details
Utilizza AdvancedPlaceDetailsFragment o AdvancedPlaceDetailsCompactFragment per accedere alle funzionalità avanzate.
Configurare i pulsanti di azione
Utilizza l'interfaccia PlaceActionProvider di AdvancedPlaceDetailsFragment o AdvancedPlaceDetailsCompactFragment per definire e personalizzare i pulsanti di azione.
Se utilizzi le funzioni @composable, utilizza le espressioni lambda mainActions e cornerActions per configurare i pulsanti di azione.
Requisiti di attribuzione visiva
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 le classi SearchMediaOptions e SearchReviewsOptions di AdvancedPlaceDetailsFragment o AdvancedPlaceDetailsCompactFragment per attivare la ricerca e il filtro per contenuti multimediali o recensioni.
Se utilizzi le funzioni @composable, utilizza com.google.android.libraries.places.compose.search.SearchMediaOptions per attivare la ricerca e il filtro per contenuti multimediali o recensioni.
Creare 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.
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.
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.
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.
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.
Cosa non fare
Non includere annunci, testi di marketing, sconti promozionali o inviti all'abbonamento all'interno dei contenitori di luoghi personalizzati.
Per aggiungere contenuti personalizzati, utilizza il componibile AdvancedPlaceDetailsCompact. Utilizza basicSectionTop o basicSectionBottom per specificare la posizione del contenuto.
Esempi di Place Details avanzati
Personalizzare i pulsanti di azione
Utilizza l'interfaccia PlaceActionProvider per controllare quali azioni sono disponibili per ogni luogo.
Kotlin
class PlaceDetailsWidgetTestActivity : BaseActivity() { // simplified example of starting the fragment fun setupPPDFragment() { fullWidgetSelectedContent = AdvancedPlaceDetailsFragment.ALL_CONTENT.toMutableList() AdvancedPlaceDetailsFragment.newInstance(fullWidgetSelectedContent, Orientation.VERTICAL) supportFragmentManager .beginTransaction() .replace(R.id.fragment_container, fragment!!) .commitNow() } // you can set the callback elsewhere, but this is the ideal callback spot override fun onAttachFragment(fragment: Fragment) { super.onAttachFragment(fragment) when (fragment) { is PlaceActionController -> setPlaceActionProvider(fragment) } } // have this callback return an empty list to hide all buttons // if this callback isn't set, default buttons appear private fun setPlaceActionProvider(fragment: PlaceActionController) { fragment.setPlaceActionProvider( object : PlaceActionProvider { override fun getMainPlaceActions(place: Place): List<PlaceAction> = buildList { // predefined actions can be mixed in with custom ones add(PlaceAction.OPEN_IN_MAPS) // example of button with both text label and icon add( PlaceAction.builder() .setLabelTextResId(R.string.custom_action) .setIconResId(R.drawable.gs_custom_action_icon) .setContentDescriptionResId(R.string.custom_action_description) .setOnClickListener { /* todo perform action */ } .build() ) // icon only button add( PlaceAction.builder() .setIconResId(R.drawable.custom_action_icon_2) .setContentDescriptionResId(R.string.custom_action_description_2) .setOnClickListener { /* todo perform action */} .build() ) // text label only button add( PlaceAction.builder() .setLabelTextResId(R.string.custom_action_3) .setContentDescriptionResId(R.string.custom_action_description_2) .setOnClickListener {/* todo perform action */ } .build() ) } /** You can also specify whether corner buttons should appear. For either callback, returning an empty list results in no buttons appearing */ override fun getCornerPlaceActions(place: Place): List<PlaceAction> { return emptyList() } override fun addPlaceActionsChangedListener( listener: PlaceActionProvider.OnChangedListener ) { // in this example, just one listener and widget this@HostAppActivity.listener = listener } override fun removePlaceActionsChangedListener( listener: PlaceActionProvider.OnChangedListener ) { // if there are multiple listeners, remove only the provided listener this@HostAppActivity.listener = null } }) } }
Aggiungere azioni personalizzate e predefinite
Questo esempio aggiunge un pulsante di attivazione/disattivazione per consentire a un utente di aggiungere un luogo ai preferiti o rimuoverlo.
Kotlin
private var listener: PlaceActionProvider.OnChangedListener? = null private fun setPlaceActionProvider(fragment: PlaceActionController) { fragment.setPlaceActionProvider( object : PlaceActionProvider { private var placeFavorited = false override fun getMainPlaceActions(place: Place): List<PlaceAction> { val buttonList = mutableListOf<PlaceAction>() if (placeFavorited) { buttonList.add( PlaceAction.builder() .setLabelTextResId(R.string.place_details_button_config_favorite) .setIconResId(R.drawable.gs_web_vd_theme_24) .setOnClickListener { placeFavorited = !placeFavorited refreshButtonConfigs() } .build() ) } else { buttonList.add( PlaceAction.builder() .setLabelTextResId(R.string.place_details_button_config_unfavorite) .setIconResId(R.drawable.gs_web_vd_theme_24) .setOnClickListener { placeFavorited = !placeFavorited refreshButtonConfigs() } .build() ) } return buttonList } override fun addPlaceActionsChangedListener( listener: PlaceActionProvider.OnChangedListener ) { this@PlaceDetailsWidgetTestActivity.listener = listener } override fun removePlaceActionsChangedListener( listener: PlaceActionProvider.OnChangedListener ) { // if there are multiple listeners, remove only the provided listener this@PlaceDetailsWidgetTestActivity.listener = null } } ) } private fun refreshButtonConfigs() { listener?.onPlaceActionsChanged() }
Utilizzare i pulsanti standard predefiniti
Crea pulsanti di azione che eseguono azioni standard definite da Google.
Kotlin
override fun getMainPlaceActions(place: Place): List<PlaceAction> { val buttonList = mutableListOf<PlaceAction>() // these buttons will have different background and text color than user-created buttons. // Text and icon button buttonList.add(PlaceAction.OPEN_IN_MAPS) // Icon-only buttons not enabled for main action buttons // Use of kotlin extension to do the same. see PlaceAction.OPEN_IN_MAPS { setIconResId(0) } return buttonList }
Filtrare recensioni e contenuti multimediali
Questo esempio di codice mostra solo i contenuti multimediali e le recensioni che menzionano "spaghetti" e "buoni".
Kotlin
import com.google.android.libraries.places.widget.AdvancedPlaceDetailsFragment import com.google.android.libraries.places.widget.model.SearchMediaOptions import com.google.android.libraries.places.widget.model.SearchReviewsOptions import com.google.android.libraries.places.widget.model.Orientation import com.google.android.libraries.places.R // 1. Create options using the Java builders (called from Kotlin) val mediaOptions = SearchMediaOptions.builder() .setQuery("spaghetti") .setRankPreference(SearchMediaOptions.RankPreference.MOST_RELEVANT) .build() val reviewOptions = SearchReviewsOptions.builder() .setQuery("tasty") .setRankPreference(SearchReviewsOptions.RankPreference.NEWEST) .build() // 2. Create the fragment val fragment = AdvancedPlaceDetailsFragment.newInstance( AdvancedPlaceDetailsFragment.STANDARD_CONTENT, Orientation.VERTICAL, R.style.PlacesMaterialTheme ) // 3. Apply options to the fragment fragment.applySearchMediaOptions(mediaOptions) fragment.applySearchReviewsOptions(reviewOptions)
Creare spazi per i contenuti
Kotlin
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import com.google.android.libraries.places.compose.AdvancedPlaceDetailsCompact import com.google.android.libraries.places.compose.PlaceReference @Composable fun ItineraryPlaceCard(placeId: String) { AdvancedPlaceDetailsCompact( reference = PlaceReference.PlaceId(placeId) ) { // Slot: Injected directly above the place name basicSectionTop { Text( text = "Day 2 • 2:30 PM", style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.primary ) } // Slot: Injected directly below the main action buttons basicSectionBottom { NotesCard( notes = "Great quiet atmosphere for morning meetings. Famous for house-roasted pour-overs." ) } } }