Google Maps Platform 推出 15 周年 - 查看最新资讯和公告

用于表示路线和区域的多段线和多边形

本教程介绍了如何向 Android 应用添加 Google 地图,以及如何使用多段线和多边形来表示地图上的路线和区域。

请按照本教程中的说明操作,使用 Maps SDK for Android 构建一个 Android 应用。建议以 Android Studio 作为开发环境。

获取代码

从 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 示例代码库的保存位置。
    • 在以下位置找到 Polygons 项目:
      PATH-TO-SAVED-REPO/android-samples/tutorials/Polygons
    • 选择项目目录,然后点击 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 调试工具查看日志并调试应用。

了解代码

本部分教程介绍了 Polygons 应用最重要的部分,以帮助您了解如何构建类似的应用。

检查您的 Android 清单

请注意您应用的 AndroidManifest.xml 文件中的以下元素:

  • 添加一个 meta-data 元素以嵌入编译应用时所用 Google Play 服务的版本。

    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />
    
  • 添加一个指定您的 API 密钥的 meta-data 元素。本教程附带的示例将 API 密钥的值映射到字符串 google_maps_key。在您构建应用时,Gradle 将 API 密钥从您的项目的 gradle.properties 文件复制到此字符串值。

    <meta-data
      android:name="com.google.android.geo.API_KEY"
      android:value="@string/google_maps_key" />
    

    如需了解 API 密钥如何映射到字符串值,请查看您应用的 build.gradle。它包含将字符串 google_maps_key 映射到 gradle 属性 GOOGLE_MAPS_API_KEY 的以下行:

    resValue "string", "google_maps_key",
            (project.findProperty("GOOGLE_MAPS_API_KEY") ?: "")
    

以下是一个完整的清单示例:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.polygons">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

        <!--
             The API key for Google Maps-based APIs.
        -->
        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_maps_key" />

        <activity
            android:name="com.example.polygons.PolyActivity"
            android:label="@string/title_activity_maps">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

添加地图

使用 Maps SDK for Android 显示地图。

  1. 向 Activity 的布局文件 activity_maps.xml 添加 <fragment> 元素。此元素定义一个 SupportMapFragment 以充当地图的容器,并提供 GoogleMap 对象的访问权限。本教程使用 Android 支持库版本的地图 Fragment,以确保与较早版本的 Android 框架向后兼容。

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.example.polygons.PolyActivity" />
    
    
  2. 在您的 Activity 的 onCreate() 方法中,将布局文件设置为内容视图。通过调用 FragmentManager.findFragmentById() 来获取地图 Fragment 的句柄。然后使用 getMapAsync() 进行注册以执行地图回调:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        // Retrieve the content view that renders the map.
        setContentView(R.layout.activity_maps);
    
        // Get the SupportMapFragment and request notification when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(map);
        mapFragment.getMapAsync(this);
    }
    
  3. 实现 OnMapReadyCallback 接口并替换 onMapReady() 方法。API 会在 GoogleMap 对象可用时调用此回调,以便您可以向地图添加对象并针对应用进一步自定义该对象:

    public class PolyActivity extends AppCompatActivity
            implements
                    OnMapReadyCallback,
                    GoogleMap.OnPolylineClickListener,
                    GoogleMap.OnPolygonClickListener {
    
        // More code goes here, including the onCreate() method described above.
    
        @Override
        public void onMapReady(GoogleMap googleMap) {
    
            // Add polylines and polygons to the map. This section shows just
            // a single polyline. Read the rest of the tutorial to learn more.
            Polyline polyline1 = googleMap.addPolyline(new PolylineOptions()
                    .clickable(true)
                    .add(
                            new LatLng(-35.016, 143.321),
                            new LatLng(-34.747, 145.592),
                            new LatLng(-34.364, 147.891),
                            new LatLng(-33.501, 150.217),
                            new LatLng(-32.306, 149.248),
                            new LatLng(-32.491, 147.309)));
    
            // Position the map's camera near Alice Springs in the center of Australia,
            // and set the zoom factor so most of Australia shows on the screen.
            googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(-23.684, 133.903), 4));
    
            // Set listeners for click events.
            googleMap.setOnPolylineClickListener(this);
            googleMap.setOnPolygonClickListener(this);
        }
    }
    

添加多段线以在地图上绘制线条

Polyline 是一系列相连的线段。多段线用于表示地图上位置之间的路线、路径或其他连接。

  1. 创建 PolylineOptions 对象并为其添加点。每个点代表地图上的一个位置,您使用包含纬度和经度值的 LatLng 对象来定义位置。以下代码示例可创建一个包含 6 个点的多段线。

  2. 调用 GoogleMap.addPolyline() 以将多段线添加到地图中。

    Polyline polyline1 = googleMap.addPolyline(new PolylineOptions()
            .clickable(true)
            .add(
                    new LatLng(-35.016, 143.321),
                    new LatLng(-34.747, 145.592),
                    new LatLng(-34.364, 147.891),
                    new LatLng(-33.501, 150.217),
                    new LatLng(-32.306, 149.248),
                    new LatLng(-32.491, 147.309)));
    

如果要处理多段线上的点击事件,请将多段线的 clickable 选项设为 true。本教程后面会详细介绍如何处理事件。

使用多段线存储任意数据

您可以使用多段线和其他几何图形对象存储任意数据对象。

  1. 调用 Polyline.setTag() 以使用多段线存储数据对象。以下代码定义了指示多段线类型的一个任意标记 (A)。

    Polyline polyline1 = googleMap.addPolyline(new PolylineOptions()
            .clickable(true)
            .add(
                    new LatLng(-35.016, 143.321),
                    new LatLng(-34.747, 145.592),
                    new LatLng(-34.364, 147.891),
                    new LatLng(-33.501, 150.217),
                    new LatLng(-32.306, 149.248),
                    new LatLng(-32.491, 147.309)));
    // Store a data object with the polyline, used here to indicate an arbitrary type.
    polyline1.setTag("A");
    
  2. 使用 Polyline.getTag() 检索数据,如下一部分所示。

为多段线添加自定义样式

您可以在 PolylineOptions 对象中指定各种样式属性。样式选项包括描边颜色、描边宽度,描边图案、连接类型以及顶端和末端。如果您未指定特定属性,则 API 会为该属性使用默认属性。

以下代码将圆端应用于线条末端,并根据多段线的类型应用不同的顶端,其中类型是存储在多段线的数据对象中的任意属性。此示例还指定了描边宽度、描边颜色和连接类型:

private static final int COLOR_BLACK_ARGB = 0xff000000;
private static final int POLYLINE_STROKE_WIDTH_PX = 12;

private void stylePolyline(Polyline polyline) {
    String type = "";
    // Get the data object stored with the polyline.
    if (polyline.getTag() != null) {
        type = polyline.getTag().toString();
    }

    switch (type) {
        // If no type is given, allow the API to use the default.
        case "A":
            // Use a custom bitmap as the cap at the start of the line.
            polyline.setStartCap(
                    new CustomCap(
                            BitmapDescriptorFactory.fromResource(R.drawable.ic_arrow), 10));
            break;
        case "B":
            // Use a round cap at the start of the line.
            polyline.setStartCap(new RoundCap());
            break;
    }

    polyline.setEndCap(new RoundCap());
    polyline.setWidth(POLYLINE_STROKE_WIDTH_PX);
    polyline.setColor(COLOR_BLACK_ARGB);
    polyline.setJointType(JointType.ROUND);
}

上述代码为 A 型多段线的顶端指定了自定义位图,并指定了 10 像素的参考描边宽度。API 根据参考描边宽度缩放位图。指定参考描边宽度时,请提供您在以位图图像的原始尺寸设计位图图像时使用的宽度。提示:在图像编辑器中以 100% 缩放比例打开位图图像,并参照图像绘制所需的线条描边宽度。

详细了解线帽以及用于自定义形状的其他选项。

处理多段线上的点击事件

  1. 通过调用 Polyline.setClickable() 将多段线设置为可点击。(默认情况下,多段线不可点击,并且当用户点按多段线时,您的应用不会收到通知。)

  2. 实现 OnPolylineClickListener 接口并调用 GoogleMap.setOnPolylineClickListener() 以在地图上设置监听器:

    public class PolyActivity extends AppCompatActivity
            implements
                    OnMapReadyCallback,
                    GoogleMap.OnPolylineClickListener,
                    GoogleMap.OnPolygonClickListener {
    
        @Override
        public void onMapReady(GoogleMap googleMap) {
            // Add a polyline to the map.
            Polyline polyline1 = googleMap.addPolyline((new PolylineOptions())
                    .clickable(true)
                    .add(new LatLng(-35.016, 143.321),
                            new LatLng(-34.747, 145.592),
                            new LatLng(-34.364, 147.891),
                            new LatLng(-33.501, 150.217),
                            new LatLng(-32.306, 149.248),
                            new LatLng(-32.491, 147.309)));
    
            // Set listeners for click events.
            googleMap.setOnPolylineClickListener(this);
            googleMap.setOnPolygonClickListener(this);
        }
    }
    
  3. 替换 onPolylineClick() 回调方法。以下示例会在用户每次点击多段线时,以实线和虚线交替显示描边图案:

    private static final PatternItem DOT = new Dot();
    private static final PatternItem GAP = new Gap(PATTERN_GAP_LENGTH_PX);
    //
    // Create a stroke pattern of a gap followed by a dot.
    private static final List<PatternItem> PATTERN_POLYLINE_DOTTED = Arrays.asList(GAP, DOT);
    
    @Override
    public void onPolylineClick(Polyline polyline) {
        // Flip from solid stroke to dotted stroke pattern.
        if ((polyline.getPattern() == null) || (!polyline.getPattern().contains(DOT))) {
            polyline.setPattern(PATTERN_POLYLINE_DOTTED);
        } else {
            // The default pattern is a solid stroke.
            polyline.setPattern(null);
        }
    
        Toast.makeText(this, "Route type " + polyline.getTag().toString(),
                Toast.LENGTH_SHORT).show();
    }
    

添加多边形以表示地图上的区域

Polygon 是由一系列有序排列的坐标组成的形状,类似于 Polyline。不同之处在于,多边形定义具有可填充内部的封闭区域,而多段线则是开放式的。

  1. 创建 PolygonOptions 对象并为其添加点。每个点代表地图上的一个位置,您使用包含纬度和经度值的 LatLng 对象来定义位置。以下代码示例可创建一个包含 4 个点的多边形。

  2. 通过调用 Polygon.setClickable() 将多边形设置为可点击。(默认情况下,多边形不可点击,并且当用户点按多边形时,您的应用不会收到通知。)处理多边形点击事件的方式与处理多段线上的事件类似,如本教程前面所述。

  3. 调用 GoogleMap.addPolygon() 以将多边形添加到地图中。

  4. 调用 Polygon.setTag() 以使用多边形存储数据对象。以下代码定义了多边形的一个任意类型 (alpha)。

    Polygon polygon1 = googleMap.addPolygon(new PolygonOptions()
            .clickable(true)
            .add(
                    new LatLng(-27.457, 153.040),
                    new LatLng(-33.852, 151.211),
                    new LatLng(-37.813, 144.962),
                    new LatLng(-34.928, 138.599)));
    // Store a data object with the polygon, used here to indicate an arbitrary type.
    polygon1.setTag("alpha");
    

为多边形添加自定义样式

您可以在 PolygonOptions 对象中指定多个样式属性。样式选项包括描边颜色、描边宽度、描边图案、描边连接类型和填充颜色。如果您未指定特定属性,则 API 会为该属性使用默认属性。

以下代码根据多边形的类型应用特定颜色和描边图案,其中类型是存储在多边形的数据对象中的任意属性:

private static final int COLOR_BLACK_ARGB = 0xff000000;
private static final int COLOR_WHITE_ARGB = 0xffffffff;
private static final int COLOR_GREEN_ARGB = 0xff388E3C;
private static final int COLOR_PURPLE_ARGB = 0xff81C784;
private static final int COLOR_ORANGE_ARGB = 0xffF57F17;
private static final int COLOR_BLUE_ARGB = 0xffF9A825;

private static final int POLYGON_STROKE_WIDTH_PX = 8;
private static final int PATTERN_DASH_LENGTH_PX = 20;
private static final int PATTERN_GAP_LENGTH_PX = 20;
private static final PatternItem DOT = new Dot();
private static final PatternItem DASH = new Dash(PATTERN_DASH_LENGTH_PX);
private static final PatternItem GAP = new Gap(PATTERN_GAP_LENGTH_PX);

// Create a stroke pattern of a gap followed by a dash.
private static final List<PatternItem> PATTERN_POLYGON_ALPHA = Arrays.asList(GAP, DASH);

// Create a stroke pattern of a dot followed by a gap, a dash, and another gap.
private static final List<PatternItem> PATTERN_POLYGON_BETA =
        Arrays.asList(DOT, GAP, DASH, GAP);

private void stylePolygon(Polygon polygon) {
    String type = "";
    // Get the data object stored with the polygon.
    if (polygon.getTag() != null) {
        type = polygon.getTag().toString();
    }

    List<PatternItem> pattern = null;
    int strokeColor = COLOR_BLACK_ARGB;
    int fillColor = COLOR_WHITE_ARGB;

    switch (type) {
        // If no type is given, allow the API to use the default.
        case "alpha":
            // Apply a stroke pattern to render a dashed line, and define colors.
            pattern = PATTERN_POLYGON_ALPHA;
            strokeColor = COLOR_GREEN_ARGB;
            fillColor = COLOR_PURPLE_ARGB;
            break;
        case "beta":
            // Apply a stroke pattern to render a line of dots and dashes, and define colors.
            pattern = PATTERN_POLYGON_BETA;
            strokeColor = COLOR_ORANGE_ARGB;
            fillColor = COLOR_BLUE_ARGB;
            break;
    }

    polygon.setStrokePattern(pattern);
    polygon.setStrokeWidth(POLYGON_STROKE_WIDTH_PX);
    polygon.setStrokeColor(strokeColor);
    polygon.setFillColor(fillColor);
}

详细了解描边图案以及用于自定义形状的其他选项。

后续步骤

了解 Circle 对象。圆形与多边形类似,但具有反映圆形形状的属性。