新增樣式化地圖

本教學課程說明如何在 Android 應用程式中加入包含自訂樣式的地圖,這裡使用「夜間模式」做為自訂樣式的範例。

您可以利用樣式選項來自訂標準 Google 地圖樣式的呈現方式,以不同的視覺效果顯示道路、公園、商家及其他搜尋點等地圖項目。也就是說,您可以凸顯地圖的特定元件,或搭配應用程式樣式來顯示地圖。

樣式僅適用於 normal 地圖類型,且不會影響室內地圖

取得程式碼

從 GitHub 複製或下載 Google Maps Android API 第 2 版範例存放區

設定您的開發專案

如要在 Android Studio 中建立教學課程專案,請按照下列步驟操作。

  1. 下載安裝 Android Studio。
  2. Google Play 服務套件加入 Android Studio。
  3. 如果您在閱讀本教學課程時尚未複製或下載 Google Maps Android API 第 2 版範例存放區,請先複製或下載。
  4. 匯入教學課程專案:

    • 在 Android Studio 中,選取 [File] (檔案) > [New] (新增) > [Import Project] (匯入專案)
    • 下載完成後,請前往您儲存 Google Maps Android API 第 2 版範例存放區的位置。
    • 在這個位置找到 StyledMap 專案:
      PATH-TO-SAVED-REPO/android-samples/tutorials/StyledMap
    • 選取專案目錄,然後按一下 [OK] (確定)。Android Studio 現在會使用 Gradle 建構工具來建立您的專案。

取得 API 金鑰並啟用必要的 API

如想完成本教學課程,您必須取得獲授權使用 Maps SDK for Android 的 Google API 金鑰。

點選下方按鈕即可取得金鑰並啟用 API。

取得金鑰

詳情請參閱取得 API 金鑰指南。

在應用程式中加入 API 金鑰

  1. 編輯專案的 gradle.properties 檔案。
  2. 將 API 金鑰貼到 GOOGLE_MAPS_API_KEY 屬性的值中。在您建構應用程式時,Gradle 會將 API 金鑰複製到應用程式的 Android 資訊清單中。

    GOOGLE_MAPS_API_KEY=PASTE-YOUR-API-KEY-HERE
    

建構並執行應用程式

  1. 將 Android 裝置連接到電腦。按照操作說明為 Android 裝置啟用開發人員選項,並將系統設定為偵測裝置 (您也可以使用 Android Virtual Device (AVD) Manager 來設定虛擬裝置。選擇模擬器時,請務必挑選包含 Google API 的映像檔。詳情請參閱入門指南)。
  2. 在 Android Studio 中,按一下 [Run] (執行) 選單選項 (或播放按鈕圖示), 然後按照系統提示選擇裝置。

Android Studio 會叫用 Gradle 來建構應用程式,然後在裝置或模擬器上執行應用程式。您應該會看到一個顏色較深的地圖 (夜間模式),類似本頁的圖片。

疑難排解:

  • 如未看到地圖,請檢查您是否已按照上述步驟取得 API 金鑰,並將其加入應用程式。在 Android Studio 中查看 Android Monitor 中的記錄檔,看看是否有關於 API 金鑰的錯誤訊息。
  • 使用 Android Studio 偵錯工具查看記錄檔並為應用程式偵錯。

瞭解程式碼

本教學課程這一段將說明 StyledMap 應用程式最重要的部分,協助您瞭解如何建構類似的應用程式。

新增包含 JSON 樣式物件的資源

在開發專案中新增資源,其中包含 JSON 格式的樣式宣告。您可以使用原始資源或字串,如下方範例所示。

原始資源

/res/raw/style_json.json 中定義原始資源,其中包含夜間模式樣式的 JSON 樣式宣告:

字串資源

/res/values/style_strings.xml 中定義字串資源,其中包含夜間模式樣式的 JSON 樣式宣告。本教學課程使用 style_json 這個字串名稱。在這個檔案中,您必須使用反斜線來逸出引號:

將 JSON 樣式物件傳遞至地圖

設定地圖樣式時,請呼叫 GoogleMap.setMapStyle(),並傳遞包含 JSON 格式樣式宣告的 MapStyleOptions 物件。

原始資源

下列程式碼範例假設您的專案含有名為 style_json 的原始資源:

// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.example.styledmap;

import android.content.res.Resources;
import android.os.Bundle;
import android.util.Log;
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.MapStyleOptions;

/**
 * A styled map using JSON styles from a raw resource.
 */
public class MapsActivityRaw extends AppCompatActivity
        implements OnMapReadyCallback {

    private static final String TAG = MapsActivityRaw.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Retrieve the content view that renders the map.
        setContentView(R.layout.activity_maps_raw);

        // Get the SupportMapFragment and register for the callback
        // when the map is ready for use.
        SupportMapFragment mapFragment =
                (SupportMapFragment) getSupportFragmentManager()
                        .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    /**
     * Manipulates the map when it's available.
     * The API invokes this callback when the map is ready for use.
     */
    @Override
    public void onMapReady(GoogleMap googleMap) {

        try {
            // Customise the styling of the base map using a JSON object defined
            // in a raw resource file.
            boolean success = googleMap.setMapStyle(
                    MapStyleOptions.loadRawResourceStyle(
                            this, R.raw.style_json));

            if (!success) {
                Log.e(TAG, "Style parsing failed.");
            }
        } catch (Resources.NotFoundException e) {
            Log.e(TAG, "Can't find style. Error: ", e);
        }
        // Position the map's camera near Sydney, Australia.
        googleMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(-34, 151)));
    }
}

版面配置 (activity_maps_raw.xml) 如下所示:

字串資源

下列程式碼範例假設您的專案含有名為 style_json 的字串資源:

package com.example.styledmap;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

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.MapStyleOptions;

/**
 * A styled map using JSON styles from a string resource.
 */
public class MapsActivityString extends AppCompatActivity
        implements OnMapReadyCallback {

    private static final String TAG = MapsActivityString.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Retrieve the content view that renders the map.
        setContentView(R.layout.activity_maps_string);

        // Get the SupportMapFragment and register for the callback
        // when the map is ready for use.
        SupportMapFragment mapFragment =
                (SupportMapFragment) getSupportFragmentManager()
                        .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    /**
     * Manipulates the map when it's available.
     * The API invokes this callback when the map is ready for use.
     */
    @Override
    public void onMapReady(GoogleMap googleMap) {

        // Customise the styling of the base map using a JSON object defined
        // in a string resource file. First create a MapStyleOptions object
        // from the JSON styles string, then pass this to the setMapStyle
        // method of the GoogleMap object.
        boolean success = googleMap.setMapStyle(new MapStyleOptions(getResources()
                .getString(R.string.style_json)));

        if (!success) {
            Log.e(TAG, "Style parsing failed.");
        }
        // Position the map's camera near Sydney, Australia.
        googleMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(-34, 151)));
    }
}

版面配置 (activity_maps_string.xml) 如下所示:

其他 JSON 樣式宣告相關資訊

樣式化地圖使用以下兩種概念,將顏色和其他樣式變更套用至地圖:

  • 「選取器程式碼」會指定您可以在地圖上設定樣式的地理元件,包括道路、公園、水域等等,以及這些地點的標籤。選取器程式碼包含「地圖項目」和「元素」,指定為 featureTypeelementType 屬性。
  • 「樣式函數」是可套用至地圖元素的顏色和能見度屬性;這類屬性會透過色調、色彩以及亮度/Gamma 值的組合來定義顯示的顏色。

如需 JSON 樣式選項的詳細說明,請參閱樣式參考資料

地圖平台樣式精靈

使用地圖平台樣式精靈快速產生 JSON 樣式物件。Maps SDK for Android 支援與 Maps JavaScript API 相同的樣式宣告。

後續步驟

瞭解如何透過樣式設定在地圖上隱藏地圖項目