Platform seçin: Android iOS JavaScript

Yer ayrıntıları bileşeni

Places UI Kit'in Yer Ayrıntıları bileşeni, uygulamanızda yer ayrıntılarını gösteren bağımsız bir kullanıcı arayüzü bileşeni eklemenize olanak tanır. Bu bileşen özelleştirilebilir.

Yer ayrıntıları kompakt bileşeni

Yer Ayrıntıları bileşeni bağımsız olarak veya diğer Google Haritalar Platformu API'leri ve hizmetleriyle birlikte kullanılabilir. Bileşen, Yer Kimliği, kaynak adı veya enlem/boylam koordinatlarını alır ve oluşturulmuş Yer Ayrıntıları bilgilerini döndürür.

Yer Ayrıntıları bileşeni tamamen temalandırılabilir. Böylece, kullanım alanınıza ve görsel marka kurallarınıza uygun olarak yazı tiplerini, renkleri ve köşe yarıçaplarını özelleştirebilirsiniz. PlacesMaterialTheme öğesini genişleten ve tema özelliklerini geçersiz kılan bir tema oluşturarak yer ayrıntılarının görünümünü özelleştirebilirsiniz. Ayrıca, her biri yer hakkında gösterilen bir bilgi parçasına karşılık gelen bir içerik girişi listesi belirterek hangi yer ayrıntıları alanlarının dahil edileceğini de özelleştirebilirsiniz.

Düzen varyantları

Yer Ayrıntıları bileşeni iki ana düzen varyantını destekler:

  • Kompakt: Önemli bilgileri önizlemek için kullanılan düzen.
  • Tam: Mevcut tüm yer ayrıntılarını gösteren kapsamlı düzen.

Kompakt düzen, dikey veya yatay yönde görüntülenebilir. Bu sayede bileşeni çeşitli tasarım düzenlerine ve ekran boyutlarına entegre edebilirsiniz. Tam düzen yalnızca dikey olarak görüntülenebilir.

yatay ve dikey düzenler
Yatay ve dikey düzenler

Yer Ayrıntıları bileşeni, bileşende gösterilen içerik üzerinde ayrıntılı kontrol sahibi olmanızı sağlar. Her öğe (ör. fotoğraflar, yorumlar ve iletişim bilgileri) ayrı ayrı gösterilebilir veya gizlenebilir. Böylece bileşenlerin görünümü ve bilgi yoğunluğu hassas bir şekilde özelleştirilebilir.

Yer ayrıntıları içerik seçenekleri
İçerik görüntüleme seçenekleri

Yer ayrıntıları kompakt görünümü

Yer ayrıntıları kompakt parçası (PlaceDetailsCompactFragment), seçilen bir yerin ayrıntılarını en az yer kullanarak oluşturur. Bu, haritadaki bir yeri vurgulayan bilgi penceresinde, sohbette konum paylaşma gibi bir sosyal medya deneyiminde, mevcut konumunuzu seçme önerisi olarak veya Google Haritalar'daki yere referans vermek için bir medya makalesinde faydalı olabilir.

Yer ayrıntılarının tam görünümü

Yer ayrıntılarının tam görünümü (PlaceDetailsFragment), yer ayrıntıları bilgilerini göstermek için daha büyük bir alan sunar ve daha fazla bilgi türü göstermenize olanak tanır.

İçerik görüntüleme seçenekleri

PlaceDetailsCompactFragment.Content veya PlaceDetailsFragment.Content içindeki numaralandırmaları kullanarak hangi içeriğin gösterileceğini belirtebilirsiniz.

Kompakt görünüm Tam görünüm
  • Yer fotoğrafı
  • Yer adresi
  • Puan ve puan sayısı
  • Yer türü
  • Fiyat
  • Tekerlekli sandalyeye uygun giriş bilgileri
  • Şu anda açık durumu
  • Yer fotoğrafı kolajı
  • Yer adresi
  • Puan ve puan sayısı
  • Yer türü
  • Fiyat
  • Erişilebilirlik bilgileri
  • Şu anda açık durumu
  • Çalışma saatleri
  • İçerik özeti
  • Web sitesi
  • Telefon numarası
  • Yorumlar özel sekmede gösterilir.
  • Plus code
  • Özel bir sekmede oluşturulan özellik listesi
  • Türe özgü önemli noktalar (ör. benzin istasyonları için benzin fiyatları)

Faturalandırma

Yer Ayrıntıları UI Kit'i kullanılırken .loadWithPlaceId(), .loadWithResourceName() veya loadWithCoordinates() yöntemi her çağrıldığında faturalandırılırsınız. Aynı yeri birden fazla kez yüklerseniz her istek için faturalandırılırsınız.

Birden fazla kez ödeme alınmaması için .loadWithPlaceId() veya .loadWithResourceName() öğelerini doğrudan Android yaşam döngüsü yöntemlerine eklemeyin. Örneğin, onResume() yönteminde .loadWithPlaceId() veya .loadWithResourceName()'u doğrudan çağırmayın.

Uygulamanıza yer ayrıntıları ekleme

Bir düzene parça ekleyerek uygulamanıza yer ayrıntıları ekleyebilirsiniz. Parçayı oluşturduğunuzda, yer ayrıntıları bilgilerinin görünümünü ve tarzını ihtiyaçlarınıza ve uygulamanızın görünümüne uyacak şekilde özelleştirebilirsiniz. Özelleştirme hakkında daha fazla bilgi edinin.

Hem Kotlin hem de Java'da kullanabileceğiniz üç yöntem vardır: biri parçayı yer kimliğiyle (loadWithPlaceId()), biri parçayı kaynak adıyla (loadWithResourceName()), biri de parçayı enlem/boylam koordinatlarıyla (loadWithCoordinates()) yüklemek için kullanılır. Bu yöntemlerden herhangi birini veya birden fazlasını seçebilirsiniz.

Kompakt görünümün varsayılan konumu dikey moddur. Yatay düzen istiyorsanız Orientation.HORIZONTAL değerini belirtin. Dilerseniz netlik için Orientation.VERTICAL de belirtebilirsiniz. Tam görünüm yalnızca dikey olarak görüntülenebilir.

Örnekleri Yer Ayrıntıları bileşeni örnekleri bölümünde bulabilirsiniz.

Görsel görünümü özelleştirme

Yer ayrıntıları görsel özelleştirme
Görsel özelleştirme örnekleri

Places UI kiti, görsel özelleştirme için kabaca Material Design'a (Google Haritalar'a özgü bazı değişikliklerle) dayalı bir tasarım sistemi yaklaşımı sunar. Renk ve Yazı Biçimi ile ilgili Materyal Tasarım referansına bakın. Varsayılan olarak, stil Google Haritalar'ın görsel tasarım diline uygundur.

Yer ayrıntılarını özelleştirme seçenekleri

Bir parçayı örneklendirirken varsayılan stil özelliklerinden herhangi birini geçersiz kılan bir tema belirtebilirsiniz. Geçersiz kılınmayan tüm tema özellikleri varsayılan stilleri kullanır. Koyu temayı desteklemek istiyorsanız values-night/colors.xml içinde renk için bir giriş ekleyebilirsiniz.

  <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>

Aşağıdaki stilleri özelleştirebilirsiniz:

İletişim kutusu rengi ve tipografi özelleştirme
İletişim kutusu rengi ve tipografi özelleştirme
Theme özelliği Kullanım
Renk
placesColorSurface Kapsayıcı ve iletişim kutusu arka planı
placesColorOutlineDecorative Kapsayıcı kenarlığı
placesColorPrimary Bağlantılar, yükleme göstergesi, genel bakış simgeleri
placesColorOnSurface Başlıklar, iletişim kutusu içeriği
placesColorOnSurfaceVariant Yer bilgileri
placesColorSecondaryContainer Düğme arka planı
placesColorOnSecondaryContainer Düğme metni ve simgesi
placesColorNeutralContainer Tarih rozetini ve yükleme yer tutucu şekillerini inceleme
placesColorOnNeutralContainer İnceleme tarihi, yükleme hatası
placesColorPositiveContainer EV şarj noktası rozeti
placesColorOnPositiveContainer Mevcut EV şarj cihazı rozeti içeriği
placesColorPositive "Şu anda açık" etiketini yerleştirme
placesColorNegative Yerlere "Kapalı" etiketi ekleme
placesColorInfo Tekerlekli sandalyeye uygun giriş simgesi
placesColorButtonBorder Haritalar'da aç ve Tamam düğmeleri
   
Tipografi (Typography)
placesTextAppearanceBodySmall Yer bilgileri
placesTextAppearanceBodyMedium Yer bilgileri, iletişim kutusu içeriği
placesTextAppearanceLabelMedium Rozet içeriği
placesTextAppearanceLabelLarge Düğme içeriği
placesTextAppearanceHeadlineMedium İletişim kutusu başlıkları
placesTextAppearanceDisplaySmall Yer adı
placesTextAppearanceTitleSmall Yer adı
   
Boşluk
placesSpacingExtraSmall
placesSpacingSmall
placesSpacingMedium
placesSpacingLarge
placesSpacingExtraLarge
placesSpacingTwoExtraLarge
   
Ölçüm
placesBorderWidth Kapsayıcı
placesBorderWidthButton
   
Şekil
placesCornerRadius Kapsayıcı
placesCornerRadiusButton Haritalar'da aç ve Tamam düğmeleri (yuvarlak simge düğmesi hariç)
placesCornerRadiusThumbnail Yer küçük resmi
placesCornerRadiusCollageOuter Medya kolajı
placesCornerRadiusCard Yer kartı, kullanıcı yorumu kartı
placesCornerRadiusDialog Google Haritalar açıklama iletişim kutusu
   
Google Haritalar'da Marka İlişkilendirmesi
placesColorAttributionLightTheme Açık tema Google Haritalar ilişkilendirme ve açıklama düğmesi (beyaz, gri ve siyah için numaralandırılmış değerler)
placesColorAttributionDarkTheme Koyu tema Google Haritalar ilişkilendirme ve açıklama düğmesi (beyaz, gri ve siyah için numaralandırmalar)

Örnekleri Yer Ayrıntıları bileşeni örnekleri bölümünde bulabilirsiniz.

Genişlik ve yükseklik özelleştirme

Kompakt görünümler

Önerilen genişlikler:

  • Dikey yön: 180 dp ile 300 dp arasında.
  • Yatay yön: 180 dp ile 500 dp arasında.

160 dp'den küçük genişlikler doğru şekilde görüntülenmeyebilir.

En iyi uygulama, kompakt görünümler için yükseklik ayarlamamaktır. Bu sayede penceredeki içerik yüksekliği ayarlayabilir ve tüm bilgilerin gösterilmesini sağlayabilirsiniz.

Tam görüntüleme sayısı

Tam görünümler için önerilen genişlik 250 dp ile 450 dp arasındadır. 250 dp'den küçük bir genişlik doğru şekilde görüntülenmeyebilir.

Bileşenin yüksekliğini ayarlayabilirsiniz: Dikey yer ayrıntıları görünümü, ayrılan alan içinde dikey olarak kaydırılır.

En iyi uygulama, tam görünümler için bir yükseklik belirlemektir. Bu sayede penceredeki içerik düzgün şekilde kaydırılabilir.

İlişkilendirme renkleri

ilişkilendirme
İlişkilendirme

Google Haritalar Hizmet Şartları, Google Haritalar ilişkilendirmesi için üç marka renginden birini kullanmanızı zorunlu kılar. Özelleştirme değişiklikleri yapıldığında bu ilişkilendirme görünür ve erişilebilir olmalıdır.

Açık ve koyu temalar için bağımsız olarak ayarlanabilen 3 marka rengi seçeneği sunuyoruz:

  • Açık tema: Beyaz, gri ve siyah için enum değerleriyle placesColorAttributionLight.
  • Koyu tema: placesColorAttributionDark beyaz, gri ve siyah için enum değerleriyle.

Yer ayrıntıları bileşeni örnekleri

Kompakt veya tam görünüm oluşturma

Kotlin

              
        // 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)
        }
    }

Java

      
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);

Bu tam kod örneği, kullanıcının cihazının yapılandırmasına göre kompakt görünümün yönünü programatik olarak belirler.

Kotlin

        
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
    }
}
        
  
İpucu: GitHub'da tam kod örneklerine erişin.

Tema oluşturma

Bir parçayı örneklendirirken varsayılan stil özelliklerinden herhangi birini geçersiz kılan bir tema belirtebilirsiniz. Geçersiz kılınmayan tüm tema özellikleri varsayılan stilleri kullanır. Koyu temayı desteklemek istiyorsanız values-night/colors.xml içinde renk için bir giriş ekleyebilirsiniz.

  <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>

Standart içerik kullanma

Bu örnekte standart içerik kullanılmaktadır.

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

Belirli içerikleri özelleştirme

Bu örnekte, kompakt bir görünüm için yalnızca adres, erişilebilir giriş ve medya Content seçenekleri belirlenir ve bunlar CustomizedPlaceDetailsTheme ile oluşturulur.

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

Tüm içeriği kullanma

Bu örnekte, kompakt görünümün tüm Content seçenekleri kullanılmaktadır.

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