Kit de IU de Places Details (experimental)

Vista compacta de los detalles del lugar

El kit de IU de Place Details te permite agregar un componente de IU individual que muestre los detalles de los lugares en tu app. El kit de IU se puede usar de forma independiente o en conjunto con otras APIs y servicios de Google Maps Platform. El kit de la IU toma un ID de lugar o coordenadas de latitud y longitud, y muestra la información renderizada de Place Details.

El kit de IU ofrece una vista compacta, que se puede mostrar horizontal o verticalmente. Para personalizar la apariencia de los detalles del lugar, anula cualquiera de los atributos del tema predeterminado. También puedes personalizar qué campos de detalles del lugar se incluyen especificando una lista de entradas Content, cada una de las cuales corresponde a un dato que se muestra sobre el lugar.

Facturación

Cuando usas el kit de IU de Place Details, se te factura cada vez que se llama al método .loadPlaceDetails(). Si cargas el mismo lugar varias veces, se te facturará por cada solicitud. Para evitar que se te cobre varias veces, no agregues .loadPlaceDetails() directamente en los métodos de ciclo de vida de Android. Por ejemplo, no llames directamente a .loadPlaceDetails() en el método onResume().

Habilita el kit de IU de Places

Antes de usar el kit de IU de Places, debes hacer lo siguiente:

Ejemplos del kit de IU de Place Details

Para agregar detalles de lugares a tu app, agrega un fragmento a un diseño. Cuando creas una instancia del fragmento, puedes personalizar el aspecto de la información de los detalles del lugar para que se adapte a tus necesidades y coincida con el aspecto de tu app.

Puedes especificar la orientación (horizontal o vertical), las anulaciones de temas y el contenido. Las opciones de contenido son medios, dirección, calificación, precio, tipo, entrada accesible, vínculo a Maps y vínculo a instrucciones sobre cómo llegar. Consulta un ejemplo de personalización.

Kotlin

val fragment = PlaceDetailsCompactFragment.newInstance(
  orientation,
  listOf(Content.ADDRESS, Content.TYPE, Content.RATING, Content.ACCESSIBLE_ENTRANCE),
  R.style.CustomizedPlaceDetailsTheme,
)
      
fragment.setPlaceLoadListener(object : PlaceLoadListener {
    override fun onSuccess() { ... }
      
      override fun onFailure(e: Exception) { ... }
})
      
supportFragmentManager
  .beginTransaction()
  .add(R.id.fragment_container, fragment)
  .commitNow()
      
fragment.loadPlaceDetails(placeId)

Java

      
PlaceDetailsCompactFragment fragment =
  PlaceDetailsCompactFragment.newInstance(
        Orientation.HORIZONTAL,
        Arrays.asList(Content.ADDRESS, Content.TYPE, Content.RATING, Content.ACCESSIBLE_ENTRANCE),
        R.style.CustomizedPlaceDetailsTheme);
    
fragment.setPlaceLoadListener(
  new PlaceLoadListener() {
        @Override
        public void onSuccess() { ... }
    
        @Override
        public void onFailure(Exception e) { ... }
});
    
getSupportFragmentManager()
      .beginTransaction()
      .add(R.id.fragment_container, fragment)
      .commitNow();
    
fragment.loadPlaceDetails(placeId);

Consulta el código completo para cargar el widget de Place Details

Kotlin

        import android.os.Bundle
        import android.util.Log
        import android.view.View
        import android.widget.FrameLayout
        import androidx.appcompat.app.AppCompatActivity
        import com.google.android.gms.maps.CameraUpdateFactory
        import com.google.android.gms.maps.GoogleMap
        import com.google.android.gms.maps.OnMapReadyCallback
        import com.google.android.gms.maps.SupportMapFragment
        import com.google.android.gms.maps.model.LatLng
        import com.google.android.gms.maps.model.PointOfInterest
        import com.google.android.libraries.places.api.Places
        import com.google.android.libraries.places.api.net.PlacesClient
        import com.google.android.libraries.places.widget.PlaceDetailsCompactFragment
        import com.google.android.libraries.places.widget.PlaceDetailsCompactFragment.Companion.ALL_CONTENT
        import com.google.android.libraries.places.widget.model.Orientation
        
        class MainActivity : AppCompatActivity(), OnMapReadyCallback, GoogleMap.OnPoiClickListener {
            private var googleMap: GoogleMap? = null
            private val orientation: Orientation = Orientation.HORIZONTAL
            private lateinit var placesClient: PlacesClient
            private var placeDetailsFragment: PlaceDetailsCompactFragment? = null
        
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setContentView(R.layout.activity_main)
        
                // --- Initialize Places SDK ---
                val apiKey = BuildConfig.PLACES_API_KEY
                if (apiKey.isEmpty()) {
                    Log.e("Places test", "No api key")
                    finish()
                    return
                }
                Places.initializeWithNewPlacesApiEnabled(applicationContext, apiKey)
                placesClient = Places.createClient(this)
                // -----------------------------
        
                val mapFragment = supportFragmentManager.findFragmentById(R.id.map_fragment) as SupportMapFragment?
                mapFragment?.getMapAsync(this)
            }
        
            override fun onMapReady(map: GoogleMap) {
                googleMap = map
                val sydney = LatLng(-33.8688, 151.2093)
                val zoomLevel = 13f
                googleMap?.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, zoomLevel))
                googleMap?.setOnPoiClickListener(this)
            }
        
            override fun onPoiClick(poi: PointOfInterest) {
                val placeId = poi.placeId
                Log.d("POI Click", "Place ID: $placeId")
                showPlaceDetailsFragment(placeId)
            }
        
            private fun showPlaceDetailsFragment(placeId: String) {
                placeDetailsFragment = PlaceDetailsCompactFragment.newInstance(
                    orientation,
                    ALL_CONTENT
                )
                supportFragmentManager
                    .beginTransaction()
                    .replace(findViewById<FrameLayout>(R.id.place_details_fragment_host).id, placeDetailsFragment!!)
                    .commitNow()
                placeDetailsFragment?.loadPlaceDetails(placeId)
            }
        }               
        
        

Ejemplo de personalización

Cuando creas una instancia de un fragmento, puedes especificar un tema que anule cualquiera de los atributos de estilo predeterminados. Los atributos de tema que no se anulen usarán los estilos predeterminados. Si deseas admitir un tema oscuro, puedes agregar una entrada para el color en values-night/colors.xml.

  <style name="CustomizedPlaceDetailsTheme" parent="PlacesTheme">
    <item name="placesColorPrimary">@color/app_primary_color</item>
    <item name="placesColorOnSurface">@color/app_color_on_surface</item>
    <item name="placesColorOnSurfaceVariant">@color/app_color_on_surface</item>
  
    <item name="placesTextAppearanceBodySmall">@style/app_text_appearence_small</item>
  
    <item name="placesCornerRadius">20dp</item>
  </style>

Puedes personalizar los siguientes estilos:

  • placesColorSurfaceContainerLowest
  • placesColorOutlineDecorative
  • placesColorPrimary
  • placesColorOnSurface
  • placesColorOnSurfaceVariant
  • placesColorSecondaryContainer
  • placesColorOnSecondaryContainer
  • placesCornerRadius
  • placesTextAppearanceBodySmall
  • placesTextAppearanceBodyMedium
  • placesTextAppearanceBodyLarge
  • placesTextAppearanceLabelLarge
  • placesTextAppearanceHeadlineMedium
  • placesColorAttributionLight (enums para blanco, gris y negro)
  • placesColorAttributionDark (enums para blanco, gris y negro)

En este ejemplo, se personaliza el contenido estándar.

  val fragmentStandardContent = PlaceDetailsCompactFragment.newInstance(
  orientation,
  PlaceDetailsCompactFragment.STANDARD_CONTENT,
  R.style.BrandedPlaceDetailsTheme,
)

En este ejemplo, se personaliza todo el contenido.

  val fragmentAllContent = PlaceDetailsCompactFragment.newInstance(
  orientation,
  PlaceDetailsCompactFragment.ALL_CONTENT,
  R.style.BrandedPlaceDetailsTheme,
)