添加自定样式的地图

本教程介绍了如何将带自定义样式的地图添加到 Android 应用。本教程将“夜间模式”作为自定义样式的示例。

您可以使用样式选项自定义标准 Google 地图样式的外观风格,更改道路、公园、商家和其他地图注点等地图项的视觉显示效果。这意味着,您可以突出地图的特定组件或根据应用的样式创建地图组件。

样式设置仅适用于 normal 地图类型。样式设置不会影响室内地图

获取代码

从 GitHub 克隆或下载 Google Maps Android API v2 示例代码库

设置您的开发项目

按照以下步骤在 Android Studio 中创建教程项目。

  1. 下载安装 Android Studio。
  2. Google Play 服务软件包添加到 Android Studio。
  3. 克隆或下载 Google Maps Android API v2 示例代码库(如果您在开始阅读本教程之前尚未执行此操作)。
  4. 导入教程项目:

    • 在 Android Studio 中,依次选择 File > New > Import Project
    • 转到已下载的 Google Maps Android API v2 示例代码库的保存位置。
    • 在以下位置找到 MapWithMarker 项目:
      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 虚拟设备 (AVD) 管理器来配置虚拟设备。选择模拟器时,请务必选择一个包含 Google API 的映像。如需了解详情,请参阅入门指南。)
  2. 在 Android Studio 中,点击 Run 菜单选项(或 play 按钮图标)。按提示选择设备。

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 属性表示。
  • 样式器:可应用于地图元素的颜色和可见性属性。它们通过色调、颜色和亮度/灰度系数值的组合定义显示的颜色。

有关 JSON 样式设置选项的详细说明,请参阅样式参考

Maps Platform 样式设置向导

使用 Maps Platform 样式设置向导可以快速生成一个 JSON 样式设置对象。Maps SDK for Android 支持与 Maps JavaScript API 相同的样式声明。

后续步骤

了解如何通过样式设置隐藏地图上的地图项