Выберите платформу: Android iOS JavaScript

Компонент «Сведения о месте»

Компонент Place Details из Places UI Kit позволяет добавить отдельный компонент пользовательского интерфейса, отображающий информацию о месте в вашем приложении. Этот компонент можно настраивать.

Разместите детали компактного компонента

Компонент «Сведения о месте» можно использовать независимо или совместно с другими API и сервисами платформы Google Карт. Компонент принимает идентификатор места , имя ресурса или координаты широты/долготы и возвращает визуализированную информацию о месте .

Компонент «Сведения о месте» полностью поддерживает темы оформления, позволяя настраивать шрифты, цвета и радиусы скругления углов в соответствии с вашими вариантами использования и визуальными правилами бренда. Вы можете настроить внешний вид сведений о месте, создав тему, расширяющую PlacesMaterialTheme и переопределяющую атрибуты темы. Вы также можете настроить, какие поля сведений о месте будут включены, указав список записей «Содержимое», каждая из которых соответствует отображаемой информации о месте.

Варианты компоновки

Компонент «Сведения о месте» поддерживает два основных варианта макета:

  • Компактный: макет для предварительного просмотра ключевой информации.
  • Полный: Подробный макет, отображающий все доступные сведения о месте.

Компактный макет может отображаться как в вертикальной, так и в горизонтальной ориентации. Это позволяет интегрировать компонент в различные макеты дизайна и на экраны различных размеров. Полный макет может отображаться только вертикально.

горизонтальные и вертикальные макеты
Горизонтальные и вертикальные макеты

Компонент «Сведения о месте» обеспечивает детальное управление отображаемым контентом. Каждый элемент (например, фотографии, отзывы и контактная информация) можно отображать или скрывать индивидуально, что позволяет точно настраивать внешний вид компонента и плотность отображения информации.

Параметры содержимого сведений о месте
Варианты отображения контента

Компактный вид сведений о месте

Компактный фрагмент «Сведения о месте» ( PlaceDetailsCompactFragment ) отображает сведения о выбранном месте, занимая минимальное пространство. Это может быть полезно в информационном окне, выделяющем место на карте, в социальных сетях, например, для публикации местоположения в чате, в качестве подсказки для выбора текущего местоположения или в медиа-статье для упоминания места на Google Картах.

Подробности места полный просмотр

Полный вид сведений о месте ( PlaceDetailsFragment ) обеспечивает большую поверхность для отображения сведений о месте и позволяет отображать больше типов информации.

Варианты отображения контента

Вы можете указать, какой контент отображать, используя перечисления в PlaceDetailsCompactFragment.Content или PlaceDetailsFragment.Content .

Компактный вид Полный просмотр
  • Разместить фото
  • Адрес места
  • Рейтинг и количество рейтингов
  • Тип места
  • Цена
  • Информация о доступном входе
  • Статус «Открыто сейчас»
  • Разместить фотоколлаж
  • Адрес места
  • Рейтинг и количество рейтингов
  • Тип места
  • Цена
  • Информация о доступности
  • Статус «Открыто сейчас»
  • Часы работы
  • Редакционное резюме
  • Веб-сайт
  • Номер телефона
  • Обзоры отображаются на специальной вкладке
  • Плюс код
  • Список функций, представленный на специальной вкладке
  • Типичные особенности, такие как цены на бензин на АЗС

Биллинг

При использовании Place Details UI Kit плата взимается за каждый вызов методов .loadWithPlaceId() , .loadWithResourceName() или loadWithCoordinates() . При загрузке одного и того же места несколько раз плата взимается за каждый запрос.

Чтобы избежать многократного списания средств, не добавляйте .loadWithPlaceId() или .loadWithResourceName() напрямую в методы жизненного цикла Android. Например, не вызывайте .loadWithPlaceId() или .loadWithResourceName() напрямую в методе onResume() .

Добавьте информацию о месте в свое приложение

Вы можете добавить информацию о месте в своё приложение, добавив фрагмент в макет. При создании экземпляра фрагмента вы можете настроить внешний вид информации о месте в соответствии со своими потребностями и внешним видом вашего приложения. Подробнее о настройке .

В Kotlin и Java доступны три метода: один для загрузки фрагмента с идентификатором места ( loadWithPlaceId() ), один для загрузки фрагмента с именем ресурса ( loadWithResourceName() ) и один для загрузки фрагмента с координатами широты и долготы ( loadWithCoordinates() ). Вы можете выбрать любой метод или несколько.

По умолчанию компактное представление расположено вертикально. Если требуется горизонтальное расположение, укажите Orientation.HORIZONTAL . Для ясности можно также указать Orientation.VERTICAL . Полное представление может отображаться только вертикально.

См. примеры в разделе «Примеры компонента «Сведения о месте»» .

Настройте внешний вид

Визуальная настройка деталей места
Примеры визуальной настройки

Набор инструментов Places UI Kit предлагает системный подход к визуальной настройке, основанный на Material Design (с некоторыми модификациями, специфичными для Google Maps). См. раздел Material Design по цвету и типографике . По умолчанию стиль соответствует языку визуального дизайна Google Maps.

Возможности настройки сведений о месте

При создании фрагмента вы можете указать тему, которая переопределяет любые атрибуты стиля по умолчанию. Все атрибуты темы, которые не переопределяются, используют стили по умолчанию. Если вы хотите поддерживать тёмную тему, вы можете добавить запись для цвета в values-night/colors.xml .

  <style name="CustomizedPlaceDetailsTheme" parent="PlacesMaterialTheme">
    <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>

Вы можете настроить следующие стили:

Настройка цвета и типографики диалога
Настройка цвета и типографики диалога
Атрибут темы Использование
Цвет
placesColorSurface Контейнер и фон диалога
placesColorOutlineDecorative Граница контейнера
placesColorPrimary Ссылки, индикатор загрузки, значки обзора
placesColorOnSurface Заголовки, содержание диалогов
placesColorOnSurfaceVariant Информация о месте
placesColorSecondaryContainer Фон кнопки
placesColorOnSecondaryContainer Текст и значок кнопки
placesColorNeutralContainer Значок даты обзора, загрузка заполнителей
placesColorOnNeutralContainer Дата проверки, ошибка загрузки
placesColorPositiveContainer Значок доступного зарядного устройства для электромобиля
placesColorOnPositiveContainer Доступное содержимое значка зарядного устройства электромобиля
placesColorPositive Разместить этикетку «Открыто»
placesColorNegative Разместить метку «Закрыто»
placesColorInfo Значок доступного входа
placesColorButtonBorder Открыть на картах и ​​кнопках ОК
Типографика
placesTextAppearanceBodySmall Информация о месте
placesTextAppearanceBodyMedium Информация о месте, содержание диалога
placesTextAppearanceLabelMedium Содержание значка
placesTextAppearanceLabelLarge Содержимое кнопки
placesTextAppearanceHeadlineMedium Заголовки диалогов
placesTextAppearanceDisplaySmall Название места
placesTextAppearanceTitleSmall Название места
Интервал
placesSpacingExtraSmall
placesSpacingSmall
placesSpacingMedium
placesSpacingLarge
placesSpacingExtraLarge
placesSpacingTwoExtraLarge
Измерение
placesBorderWidth Контейнер
placesBorderWidthButton
Форма
placesCornerRadius Контейнер
placesCornerRadiusButton Кнопки «Открыть в Картах» и «ОК» (кроме круглой кнопки)
placesCornerRadiusThumbnail Разместить уменьшенное изображение
placesCornerRadiusCollageOuter Медиаколлаж
placesCornerRadiusCard Карточка места, Карточка отзыва пользователя
placesCornerRadiusDialog Диалог раскрытия информации в Google Картах
Атрибуция бренда Google Maps
placesColorAttributionLightTheme Кнопка атрибуции и раскрытия информации в Google Картах для светлой темы (перечисления для белого, серого и черного цветов)
placesColorAttributionDarkTheme Кнопка атрибуции и раскрытия информации в Google Картах для тёмной темы (перечисления для белого, серого и чёрного цветов)

См. примеры в разделе «Примеры компонента «Сведения о месте»» .

Настройка ширины и высоты

Компактные виды

Рекомендуемая ширина:

  • Вертикальная ориентация: от 180 до 300 dp.
  • Горизонтальная ориентация: от 180 до 500 dp.

Ширина менее 160dp может отображаться некорректно.

Рекомендуется не задавать высоту для компактных представлений. В этом случае высота будет определяться содержимым окна, что позволит отобразить всю информацию.

Полные просмотры

Для полного просмотра рекомендуемая ширина составляет от 250 до 450 dp. Ширина меньше 250 dp может отображаться некорректно.

Вы можете задать высоту компонента: вертикальное представление «Сведения о месте» будет прокручиваться вертикально в пределах отведенного пространства.

Рекомендуется задать высоту для полноэкранного режима. Это позволит содержимому окна корректно прокручиваться.

Цвета атрибуции

атрибуция
Атрибуция

Условия использования Google Карт требуют использовать один из трёх фирменных цветов для указания авторства Google Карт. Это указание должно быть видимым и доступным после внесения изменений в настройки.

Мы предлагаем на выбор 3 фирменных цвета, которые можно независимо настраивать для светлой и темной темы:

  • Светлая тема: placesColorAttributionLight со значениями перечисления для белого, серого и черного цветов.
  • Темная тема: placesColorAttributionDark со значениями перечисления для белого, серого и черного.

Примеры компонентов «Сведения о месте»

Создайте компактный или полный вид

Котлин

              
        // We create a new instance of the fragment using its factory method.
        // We can specify which content to show, the orientation, and a custom theme.
        val fragment = PlaceDetailsCompactFragment.newInstance(
            PlaceDetailsCompactFragment.ALL_CONTENT, // Show all available content.
            orientation,
            R.style.CustomizedPlaceDetailsTheme,
        ).apply {
            // The PlaceLoadListener provides callbacks for when the place data is successfully
            // loaded or when an error occurs. This is where we update our UI state.
            setPlaceLoadListener(object : PlaceLoadListener {
                override fun onSuccess(place: Place) {
                    Log.d(TAG, &quot;Place loaded: ${place.id}&quot;)
                    // Once the data is loaded, we hide the loading indicator and show the fragment.
                    binding.loadingIndicatorMain.visibility = View.GONE
                    binding.placeDetailsContainer.visibility = View.VISIBLE
                    binding.dismissButton.visibility = View.VISIBLE
                }

                override fun onFailure(e: Exception) {
                    Log.e(TAG, &quot;Place failed to load&quot;, e)
                    // On failure, we hide the UI and notify the user.
                    dismissPlaceDetails()
                    Toast.makeText(this@MainActivity, &quot;Failed to load place details.&quot;, Toast.LENGTH_SHORT).show()
                }
            })
        }

        // We add the fragment to our layout&#39;s container view.
        // `commitNow()` is used to ensure the fragment is immediately added and available,
        // which is important because we need to call a method on it right after.
        supportFragmentManager
            .beginTransaction()
            .replace(binding.placeDetailsContainer.id, fragment)
            .commitNow()

        // **This is the key step**: After adding the fragment, we call `loadWithPlaceId`
        // to trigger the data loading process for the selected place.
        // We use `post` to ensure this runs after the layout has been measured,
        // which can prevent potential timing issues.
        binding.root.post {
            fragment.loadWithPlaceId(placeId)
        }
    }

Ява

      
PlaceDetailsCompactFragment fragment =
  PlaceDetailsCompactFragment.newInstance(
        Orientation.HORIZONTAL,
        Arrays.asList(Content.ADDRESS, Content.TYPE, Content.RATING, Content.ACCESSIBLE_ENTRANCE_ICON),
        R.style.CustomizedPlaceDetailsTheme);
    
fragment.setPlaceLoadListener(
  new PlaceLoadListener() {
        @Override public void onSuccess(Place place) { ... }
    
        @Override public void onFailure(Exception e) { ... }
});
    
getSupportFragmentManager()
      .beginTransaction()
      .add(R.id.fragment_container, fragment)
      .commitNow();
    
// Load the fragment with a Place ID.
fragment.loadWithPlaceId(placeId);
      
// Load the fragment with a resource name.
fragment.loadWithResourceName(resourceName);

Этот полный пример кода программно определяет ориентацию компактного представления на основе конфигурации устройства пользователя.

Котлин

        
package com.example.placedetailsuikit

import android.Manifest
import android.annotation.SuppressLint
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.location.Location
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.lifecycle.ViewModel
import com.example.placedetailsuikit.databinding.ActivityMainBinding
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
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.model.Place
import com.google.android.libraries.places.widget.PlaceDetailsCompactFragment
import com.google.android.libraries.places.widget.PlaceLoadListener
import com.google.android.libraries.places.widget.model.Orientation

private const val TAG = &quot;PlacesUiKit&quot;

/**
 * A simple ViewModel to store UI state that needs to survive configuration changes.
 * In this case, it holds the ID of the selected place. Using a ViewModel is good practice
 * as it prevents data loss during events like screen rotation, ensuring a
 * seamless user experience.
 */
class MainViewModel : ViewModel() {
    var selectedPlaceId: String? = null
}

/**
 * This activity serves as a basic example of integrating the Place Details UI Kit.
 * It demonstrates the fundamental steps required:
 * 1. Setting up a Google Map.
 * 2. Requesting location permissions to center the map.
 * 3. Handling clicks on Points of Interest (POIs) to get a Place ID.
 * 4. Using the Place ID to load and display place details in a [PlaceDetailsCompactFragment].
 */
class MainActivity : AppCompatActivity(), OnMapReadyCallback, GoogleMap.OnPoiClickListener {
    // ViewBinding provides type-safe access to views defined in the XML layout,
    // eliminating the need for `findViewById` and preventing null pointer exceptions.
    private lateinit var binding: ActivityMainBinding
    private var googleMap: GoogleMap? = null

    // The FusedLocationProviderClient is the main entry point for interacting with the
    // fused location provider, which intelligently manages the underlying location technologies.
    private lateinit var fusedLocationClient: FusedLocationProviderClient

    // Using registerForActivityResult is the modern, recommended approach for handling
    // permission requests. It decouples the request from the handling logic, making the
    // code cleaner and easier to manage compared to the older `onRequestPermissionsResult` callback.
    private lateinit var requestPermissionLauncher: ActivityResultLauncher&lt;Array&lt;String&gt;&gt;

    // The `by viewModels()` delegate provides a lazy-initialized ViewModel scoped to this Activity.
    // This ensures that we get the same ViewModel instance across configuration changes.
    private val viewModel: MainViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // The ActivityResultLauncher is initialized here. The lambda defines the callback
        // that will be executed once the user responds to the permission dialog.
        requestPermissionLauncher =
            registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions -&gt;
                // We check if either fine or coarse location permission was granted.
                if (permissions[Manifest.permission.ACCESS_FINE_LOCATION] == true || permissions[Manifest.permission.ACCESS_COARSE_LOCATION] == true) {
                    Log.d(TAG, &quot;Location permission granted by user.&quot;)
                    fetchLastLocation()
                } else {
                    // If permission is denied, we inform the user and default to a known location.
                    // This ensures the app remains functional even without location access.
                    Log.d(TAG, &quot;Location permission denied by user.&quot;)
                    Toast.makeText(
                        this,
                        &quot;Location permission denied. Showing default location.&quot;,
                        Toast.LENGTH_LONG
                    ).show()
                    moveToSydney()
                }
            }

        // enableEdgeToEdge() allows the app to draw behind the system bars for a more immersive experience.
        enableEdgeToEdge()
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.dismissButton.setOnClickListener {
            dismissPlaceDetails()
        }

        // --- Crucial: Initialize Places SDK ---
        // It&#39;s essential to initialize the Places SDK before making any other Places API calls.
        // This should ideally be done once, for example, in the Application&#39;s `onCreate`.
        val apiKey = BuildConfig.PLACES_API_KEY
        if (apiKey.isEmpty() || apiKey == &quot;YOUR_API_KEY&quot;) {
            // A valid API key is required for the Places SDK to function.
            Log.e(TAG, &quot;No api key&quot;)
            Toast.makeText(
                this,
                &quot;Add your own API_KEY in local.properties&quot;,
                Toast.LENGTH_LONG
            ).show()
            finish()
            return
        }

        // `initializeWithNewPlacesApiEnabled` is used to opt-in to the new SDK version.
        Places.initializeWithNewPlacesApiEnabled(applicationContext, apiKey)

        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
        // ------------------------------------

        // The SupportMapFragment is the container for the map. `getMapAsync` allows us to
        // work with the GoogleMap object via a callback once it&#39;s fully initialized.
        val mapFragment =
            supportFragmentManager.findFragmentById(R.id.map_fragment) as SupportMapFragment?
        mapFragment?.getMapAsync(this)

        // This block handles restoration after a configuration change (e.g., screen rotation).
        // If a place was selected before the rotation, its ID is stored in the ViewModel.
        // We use this ID to immediately show the details fragment again.
        if (viewModel.selectedPlaceId != null) {
            viewModel.selectedPlaceId?.let { placeId -&gt;
                Log.d(TAG, &quot;Restoring PlaceDetailsFragment for place ID: $placeId&quot;)
                showPlaceDetailsFragment(placeId)
            }
        }
    }

    /**
     * This callback is triggered when the GoogleMap object is ready to be used.
     * All map setup logic should be placed here.
     */
    override fun onMapReady(map: GoogleMap) {
        Log.d(TAG, &quot;Map is ready&quot;)
        googleMap = map
        // Setting the OnPoiClickListener allows us to capture user taps on points of interest.
        googleMap?.setOnPoiClickListener(this)

        // After the map is ready, we determine the initial camera position based on location permissions.
        if (isLocationPermissionGranted()) {
            fetchLastLocation()
        } else {
            requestLocationPermissions()
        }
    }

    /**
     * A helper function to centralize the check for location permissions.
     */
    private fun isLocationPermissionGranted(): Boolean {
        return ActivityCompat.checkSelfPermission(
            this,
            Manifest.permission.ACCESS_FINE_LOCATION
        ) == PackageManager.PERMISSION_GRANTED ||
                ActivityCompat.checkSelfPermission(
                    this,
                    Manifest.permission.ACCESS_COARSE_LOCATION
                ) == PackageManager.PERMISSION_GRANTED
    }

    /**
     * This function triggers the permission request flow. The result is handled by the
     * ActivityResultLauncher defined in `onCreate`.
     */
    private fun requestLocationPermissions() {
        Log.d(TAG, &quot;Requesting location permissions.&quot;)
        requestPermissionLauncher.launch(
            arrayOf(
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.ACCESS_COARSE_LOCATION
            )
        )
    }

    /**
     * Fetches the device&#39;s last known location. This is a fast and battery-efficient way
     * to get a location fix. It should only be called after verifying permissions.
     */
    @SuppressLint(&quot;MissingPermission&quot;)
    private fun fetchLastLocation() {
        // Double-checking permissions here is a good practice, although the call sites are already guarded.
        if (isLocationPermissionGranted()) {
            fusedLocationClient.lastLocation
                .addOnSuccessListener { location: Location? -&gt;
                    if (location != null) {
                        val userLocation = LatLng(location.latitude, location.longitude)
                        googleMap?.moveCamera(CameraUpdateFactory.newLatLngZoom(userLocation, 13f))
                        Log.d(TAG, &quot;Moved to user&#39;s last known location.&quot;)
                    } else {
                        // `lastLocation` can be null if the location has never been recorded.
                        // In this case, we fall back to a default location.
                        Log.d(TAG, &quot;Last known location is null. Falling back to Sydney.&quot;)
                        moveToSydney()
                    }
                }
                .addOnFailureListener {
                    // This listener handles errors in the location fetching process.
                    Log.e(TAG, &quot;Failed to get location.&quot;, it)
                    moveToSydney()
                }
        }
    }

    /**
     * Moves the map camera to a default, hardcoded location (Sydney).
     * This serves as a reliable fallback.
     */
    private fun moveToSydney() {
        val sydney = LatLng(-33.8688, 151.2093)
        googleMap?.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney, 13f))
        Log.d(TAG, &quot;Moved to Sydney&quot;)
    }

    /**
     * This is the callback for the `OnPoiClickListener`. It&#39;s triggered when a user
     * taps a POI on the map.
     */
    override fun onPoiClick(poi: PointOfInterest) {
        val placeId = poi.placeId
        Log.d(TAG, &quot;Place ID: $placeId&quot;)

        // We save the selected place ID to the ViewModel. This is critical for surviving
        // configuration changes. If the user rotates the screen now, the `onCreate`
        // method will be able to restore the place details view.
        viewModel.selectedPlaceId = placeId
        showPlaceDetailsFragment(placeId)
    }

    /**
     * This function is the core of the integration. It creates, configures, and displays
     * the [PlaceDetailsCompactFragment].
     * @param placeId The unique identifier for the place to be displayed.
     */
    private fun showPlaceDetailsFragment(placeId: String) {
        Log.d(TAG, &quot;Showing PlaceDetailsFragment for place ID: $placeId&quot;)

        // We manage the visibility of UI elements to provide feedback to the user.
        // The wrapper is shown, and a loading indicator is displayed while the data is fetched.
        binding.placeDetailsWrapper.visibility = View.VISIBLE
        binding.dismissButton.visibility = View.GONE
        binding.placeDetailsContainer.visibility = View.GONE
        binding.loadingIndicatorMain.visibility = View.VISIBLE

        // The Place Details widget can be displayed vertically or horizontally.
        // We dynamically choose the orientation based on the device&#39;s current configuration.
        val orientation =
            if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
                Orientation.HORIZONTAL
            } else {
                Orientation.VERTICAL
            }

        
        // We create a new instance of the fragment using its factory method.
        // We can specify which content to show, the orientation, and a custom theme.
        val fragment = PlaceDetailsCompactFragment.newInstance(
            PlaceDetailsCompactFragment.ALL_CONTENT, // Show all available content.
            orientation,
            R.style.CustomizedPlaceDetailsTheme,
        ).apply {
            // The PlaceLoadListener provides callbacks for when the place data is successfully
            // loaded or when an error occurs. This is where we update our UI state.
            setPlaceLoadListener(object : PlaceLoadListener {
                override fun onSuccess(place: Place) {
                    Log.d(TAG, &quot;Place loaded: ${place.id}&quot;)
                    // Once the data is loaded, we hide the loading indicator and show the fragment.
                    binding.loadingIndicatorMain.visibility = View.GONE
                    binding.placeDetailsContainer.visibility = View.VISIBLE
                    binding.dismissButton.visibility = View.VISIBLE
                }

                override fun onFailure(e: Exception) {
                    Log.e(TAG, &quot;Place failed to load&quot;, e)
                    // On failure, we hide the UI and notify the user.
                    dismissPlaceDetails()
                    Toast.makeText(this@MainActivity, &quot;Failed to load place details.&quot;, Toast.LENGTH_SHORT).show()
                }
            })
        }

        // We add the fragment to our layout&#39;s container view.
        // `commitNow()` is used to ensure the fragment is immediately added and available,
        // which is important because we need to call a method on it right after.
        supportFragmentManager
            .beginTransaction()
            .replace(binding.placeDetailsContainer.id, fragment)
            .commitNow()

        // **This is the key step**: After adding the fragment, we call `loadWithPlaceId`
        // to trigger the data loading process for the selected place.
        // We use `post` to ensure this runs after the layout has been measured,
        // which can prevent potential timing issues.
        binding.root.post {
            fragment.loadWithPlaceId(placeId)
        }
    }


    /**
     * Hides the place details view and clears the selected place ID from the ViewModel.
     */
    private fun dismissPlaceDetails() {
        binding.placeDetailsWrapper.visibility = View.GONE
        // Clearing the ID in the ViewModel is important so that if the user rotates the
        // screen after dismissing, the details view doesn&#39;t reappear.
        viewModel.selectedPlaceId = null
    }

    override fun onDestroy() {
        super.onDestroy()
        // It&#39;s a good practice to nullify references to objects that have a lifecycle
        // tied to the activity, like the GoogleMap object, to prevent potential memory leaks.
        googleMap = null
    }
}
        
  
Совет: получите доступ к полным примерам кода на GitHub .

Создать тему

При создании фрагмента вы можете указать тему, которая переопределяет любые атрибуты стиля по умолчанию. Все атрибуты темы, которые не переопределяются, используют стили по умолчанию. Если вы хотите поддерживать тёмную тему, вы можете добавить запись для цвета в values-night/colors.xml .

  <style name="CustomizedPlaceDetailsTheme" parent="PlacesMaterialTheme">
    <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>

Использовать стандартный контент

В этом примере используется стандартное содержимое.

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

Настройте определенный контент

В этом примере выбираются только параметры адреса, доступного входа и медиа- Content для компактного представления, и они визуализируются с помощью CustomizedPlaceDetailsTheme .

  val placeDetailsFragment = PlaceDetailsCompactFragment.newInstance(
    orientation,
    listOf(
        Content.ADDRESS,
        Content.ACCESSIBLE_ENTRANCE,
        Content.MEDIA
    ),
    R.style.CustomizedPlaceDetailsTheme
)

Использовать весь контент

В этом примере используются все параметры Content компактного представления.

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