選取平台: Android iOS JavaScript

Place Details 元件

Places UI Kit 的 Place Details 元件可讓您新增個別 UI 元件,在應用程式中顯示地點詳細資料。這個元件可自訂。

地點詳細資料精簡元件

地點詳細資料元件可單獨使用,也能與其他 Google 地圖平台 API 和服務搭配使用。這個元件會採用地點 ID、資源名稱或經緯度座標,並傳回已算繪的地點詳細資料資訊。

Place Details 元件完全可套用主題,讓您自訂字型、顏色和圓角半徑,以符合您的用途和視覺品牌宣傳指南。您可以建立擴充 PlacesMaterialTheme 的主題,並提供主題屬性的覆寫,自訂地點詳細資料的外觀。您也可以指定 Content 項目清單,自訂要納入哪些地點詳細資料欄位,每個項目都對應到顯示的地點資訊。

版面配置變化版本

「地點詳細資料」元件支援兩種主要版面配置變體:

  • 精簡:預覽重要資訊的版面配置。
  • 完整:顯示所有可用地點詳細資料的完整版面配置。

緊湊版面配置可以垂直或水平顯示。因此您可以將元件整合到各種設計版面配置和螢幕大小。完整版面配置只能以直向顯示。

橫向和直向版面配置
橫向和直向版面配置

您可以精細控管「地點詳細資料」元件中顯示的內容。你可以個別顯示或隱藏各個元素 (例如相片、評論和聯絡資訊),精確自訂元件的外觀和資訊密度。

地點詳細資料內容選項
內容顯示選項

Place Details 密集檢視

Place Details 精簡片段 (PlaceDetailsCompactFragment) 會使用最少的空間,顯示所選地點的詳細資料。這項功能可能適用於醒目顯示地圖上某個地點的資訊視窗、在社群媒體體驗中分享位置資訊 (例如在即時通訊中分享位置資訊)、建議選取目前位置,或在媒體文章中參照 Google 地圖上的地點。

Place Details 完整檢視畫面

地點詳細資料完整檢視畫面 (PlaceDetailsFragment) 提供較大的介面,可顯示地點詳細資料資訊,並支援顯示更多類型的資訊。

內容顯示選項

您可以使用 PlaceDetailsCompactFragment.ContentPlaceDetailsFragment.Content 中的列舉,指定要顯示的內容。

精簡檢視 全文檢視
  • 地點相片
  • 地點地址
  • 評分和評分次數
  • 地點類型
  • 價格
  • 無障礙入口資訊
  • 營業中狀態
  • 地點相片集
  • 地點地址
  • 評分和評分次數
  • 地點類型
  • 價格
  • 無障礙設施資訊
  • 營業中狀態
  • 營業時間
  • 編輯摘要
  • 網站
  • 電話號碼
  • 在專屬分頁中顯示評論
  • Plus Code
  • 專屬分頁中顯示的功能清單
  • 特定類型的重點資訊,例如加油站的油價

帳單

使用 Place Details UI Kit 時,系統會針對每次呼叫 .loadWithPlaceId().loadWithResourceName()loadWithCoordinates() 方法收費。如果您多次載入相同地點,系統會針對每項要求向您收費。

為避免多次收費,請勿直接在 Android 生命週期方法中新增 .loadWithPlaceId().loadWithResourceName()。舉例來說,請勿在 onResume() 方法中直接呼叫 .loadWithPlaceId().loadWithResourceName()

在應用程式中新增地點詳細資料

如要在應用程式中新增地點詳細資料,請在版面配置中新增片段。例項化片段時,您可以自訂地點詳細資料資訊的外觀和風格,以符合需求並配合應用程式的外觀。進一步瞭解如何自訂

Kotlin 和 Java 都提供三種方法:一種是載入含有地點 ID 的片段 (loadWithPlaceId())、一種是載入含有資源名稱的片段 (loadWithResourceName()),另一種是載入含有經緯度座標的片段 (loadWithCoordinates())。您可以選擇任何方法,或多種方法。

緊湊檢視畫面預設為直向,如要使用水平版面配置,請指定 Orientation.HORIZONTAL。您也可以視需要指定 Orientation.VERTICAL,完整檢視畫面只能以直向顯示。

請參閱「地點詳細資料元件範例」一節中的範例。

自訂視覺外觀

自訂地點詳細資料的視覺效果
視覺自訂範例

Places UI Kit 採用設計系統方法,根據 Material Design (並進行一些 Google 地圖專屬修改) 進行視覺自訂。請參閱 Material Design 的顏色字體排版參考資料。樣式預設會採用 Google 地圖的視覺設計語言。

地點詳細資料自訂選項

例項化片段時,您可以指定主題來覆寫任何預設樣式屬性。未覆寫的主題屬性會使用預設樣式。如要支援深色主題,可以在 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 「在地圖中開啟」和「確定」按鈕
   
Typography
placesTextAppearanceBodySmall 地點資訊
placesTextAppearanceBodyMedium 地點資訊、對話內容
placesTextAppearanceLabelMedium 徽章內容
placesTextAppearanceLabelLarge 按鈕內容
placesTextAppearanceHeadlineMedium 對話方塊標題
placesTextAppearanceDisplaySmall 地點名稱
placesTextAppearanceTitleSmall 地點名稱
   
間距
placesSpacingExtraSmall
placesSpacingSmall
placesSpacingMedium
placesSpacingLarge
placesSpacingExtraLarge
placesSpacingTwoExtraLarge
   
成效評估
placesBorderWidth 容器
placesBorderWidthButton
   
形狀
placesCornerRadius 容器
placesCornerRadiusButton 「在 Google 地圖中開啟」和「確定」按鈕 (圓形圖示按鈕除外)
placesCornerRadiusThumbnail 放置縮圖
placesCornerRadiusCollageOuter 媒體美術拼貼
placesCornerRadiusCard 地點資訊卡、使用者評論資訊卡
placesCornerRadiusDialog Google 地圖揭露事項對話方塊
   
Google 地圖品牌出處資訊
placesColorAttributionLightTheme 淺色主題 Google 地圖出處和揭露資訊按鈕 (白色、灰色和黑色列舉)
placesColorAttributionDarkTheme Google 地圖深色主題的姓名標示和揭露資訊按鈕 (白色、灰色和黑色列舉)

請參閱「地點詳細資料元件範例」一節中的範例。

自訂寬度和高度

密集檢視

建議寬度:

  • 直向:介於 180dp 和 300dp 之間。
  • 橫向:介於 180dp 和 500dp 之間。

如果寬度小於 160dp,可能無法正確顯示。

最佳做法是不為精簡檢視區塊設定高度。這樣視窗中的內容就能設定高度,顯示所有資訊。

完整觀看次數

如要顯示完整檢視畫面,建議寬度介於 250dp 和 450dp 之間。如果寬度小於 250 dp,可能無法正確顯示。

您可以設定元件的高度:直向地點詳細資料檢視畫面會在分配的空間內垂直捲動。

最佳做法是為完整檢視畫面設定高度。這樣視窗中的內容就能正常捲動。

歸因顏色

歸因
歸因

根據 Google 地圖服務條款,您必須使用三種品牌顏色之一,才能標示 Google 地圖出處。進行自訂變更後,必須顯示並提供存取這個出處資訊的管道。

我們提供 3 種品牌顏色供您選擇,淺色和深色主題可分別設定:

  • 淺色主題:placesColorAttributionLight,列舉值為白色、灰色和黑色。
  • 深色主題:placesColorAttributionDark,列舉值為白色、灰色和黑色。

Place Details 元件範例

建立密集或完整檢視畫面

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

這個完整程式碼範例會根據使用者裝置的設定,以程式輔助方式決定精簡檢視區塊的方向。

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
    }
}
        
  
提示: 在 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
  )