形状

Google Maps API for Android 为您提供了一些向地图添加形状的简单方法,以便针对您的应用对其进行自定义。

  • Polyline 是一系列相连的线段,可组成您想要的任何形状,并可用于在地图上标记路径和路线。
  • Polygon 是一种封闭形状,可用于在地图上标记区域。
  • Circle 是在地图上绘制的投影图,表示一个圆形在地图表面的投影,具有地理准确性。

对于所有上述形状,您都可以通过改变若干属性来自定义其外观。

代码示例

添加多边形和多段线来表示区域和路线的教程中包含简单 Android 应用的所有代码。

此外,GitHub 上的 ApiDemos 代码库包含相关示例,展示如何使用形状及其地图项:

多段线

Polyline 类在地图上定义一组相连的线段。Polyline 对象包含一组 LatLng 位置,并可创建一系列线段,依照先后次序将这些位置连接起来。

以下这段视频就如何通过使用多段线在地图上绘制路径来帮助您的用户到达目的地提供了一些思路。

如需创建多段线,请先创建一个 PolylineOptions 对象并为其添加点。点表示地球表面上的点,以 LatLng 对象的形式表示。系统会按照您向 PolylineOptions 对象添加点的顺序在各点之间绘制线段。如需向 PolylineOptions 对象添加点,请调用 PolylineOptions.add()。请注意,该方法带有可变数量的参数,因此您可以一次添加多个点(如果点已存在于列表中,您还可以调用 PolylineOptions.addAll(Iterable<LatLng>))。

然后,您可以调用 GoogleMap.addPolyline(PolylineOptions),将多段线添加到地图中。该方法会返回 Polyline 对象,您稍后可利用该对象对多段线做出改动。

以下代码段说明了如何向地图添加矩形:

Java

// Instantiates a new Polyline object and adds points to define a rectangle
PolylineOptions polylineOptions = new PolylineOptions()
    .add(new LatLng(37.35, -122.0))
    .add(new LatLng(37.45, -122.0))  // North of the previous point, but at the same longitude
    .add(new LatLng(37.45, -122.2))  // Same latitude, and 30km to the west
    .add(new LatLng(37.35, -122.2))  // Same longitude, and 16km to the south
    .add(new LatLng(37.35, -122.0)); // Closes the polyline.

// Get back the mutable Polyline
Polyline polyline = map.addPolyline(polylineOptions);
      

Kotlin

// Instantiates a new Polyline object and adds points to define a rectangle
val polylineOptions = PolylineOptions()
    .add(LatLng(37.35, -122.0))
    .add(LatLng(37.45, -122.0)) // North of the previous point, but at the same longitude
    .add(LatLng(37.45, -122.2)) // Same latitude, and 30km to the west
    .add(LatLng(37.35, -122.2)) // Same longitude, and 16km to the south
    .add(LatLng(37.35, -122.0)) // Closes the polyline.

// Get back the mutable Polyline
val polyline = map.addPolyline(polylineOptions)
      

如需在添加多段线后改变其形状,您可以调用 Polyline.setPoints(),并为多段线提供一个新的点列表。

在将多段线添加到地图之前和之后,您都可以自定义其外观。如需进一步了解相关信息,请参阅下文有关自定义外观的部分。

多段线事件

默认情况下,多段线无法点击。您可以通过调用 Polyline.setClickable(boolean) 启用和停用可点击性。

使用 OnPolylineClickListener 可以监听可点击的多段线上的点击事件。如需在地图上设置此监听器,请调用 GoogleMap.setOnPolylineClickListener(OnPolylineClickListener)。当用户点击多段线时,您会收到 onPolylineClick(Polyline) 回调。

多边形

Polygon 对象与 Polyline 对象类似,因为它们都包含一系列有序的坐标。不过,多边形并不是开放式的,它们用于定义环路内的区域,并且内部是实心的。

您可以按照添加 Polyline 的方法向地图添加 Polygon。请先创建 PolygonOptions 对象并为其添加一些点。这些点将组成多边形的轮廓。然后通过调用 GoogleMap.addPolygon(PolygonOptions)(该选项会返回 Polygon 对象),将多边形添加到地图中。

以下代码段的作用是向地图添加一个矩形(请注意,由于我们尚未定义填充色,并且默认填充色是透明色,因此该矩形的显示效果会与上一部分代码段所生成的多段线完全一样):

Java

// Instantiates a new Polygon object and adds points to define a rectangle
PolygonOptions polygonOptions = new PolygonOptions()
    .add(new LatLng(37.35, -122.0),
        new LatLng(37.45, -122.0),
        new LatLng(37.45, -122.2),
        new LatLng(37.35, -122.2),
        new LatLng(37.35, -122.0));

// Get back the mutable Polygon
Polygon polygon = map.addPolygon(polygonOptions);
      

Kotlin

// Instantiates a new Polygon object and adds points to define a rectangle
val rectOptions = PolygonOptions()
    .add(
        LatLng(37.35, -122.0),
        LatLng(37.45, -122.0),
        LatLng(37.45, -122.2),
        LatLng(37.35, -122.2),
        LatLng(37.35, -122.0)
    )

// Get back the mutable Polygon
val polygon = map.addPolygon(rectOptions)
      

如需在添加多边形后改变其形状,您可以调用 Polygon.setPoints() 并为该多边形的轮廓提供新的点列表。

在将多边形添加到地图之前和之后,您都可以自定义其外观。如需进一步了解相关信息,请参阅下文有关自定义外观的部分。

多边形自动完成

上例中的多边形包含五个坐标,但请注意,其中第一个坐标和最后一个坐标的位置相同,这样就定义了一个环路。不过,实际上由于多边形定义的就是封闭区域,因而无需定义这最后一个坐标。如果最后一个坐标不同于第一个坐标,API 将通过在坐标序列的末尾追加第一个坐标来自动“封闭”多边形。

以下两个多边形是相同的,针对每个多边形调用 polygon.getPoints() 都将返回所有 4 个点。

Java

Polygon polygon1 = map.addPolygon(new PolygonOptions()
    .add(new LatLng(0, 0),
        new LatLng(0, 5),
        new LatLng(3, 5),
        new LatLng(0, 0))
    .strokeColor(Color.RED)
    .fillColor(Color.BLUE));

Polygon polygon2 = map.addPolygon(new PolygonOptions()
    .add(new LatLng(0, 0),
        new LatLng(0, 5),
        new LatLng(3, 5))
    .strokeColor(Color.RED)
    .fillColor(Color.BLUE));
      

Kotlin

val polygon1 = map.addPolygon(
    PolygonOptions()
        .add(
            LatLng(0.0, 0.0),
            LatLng(0.0, 5.0),
            LatLng(3.0, 5.0),
            LatLng(0.0, 0.0)
        )
        .strokeColor(Color.RED)
        .fillColor(Color.BLUE)
)
val polygon2 = map.addPolygon(
    PolygonOptions()
        .add(
            LatLng(0.0, 0.0),
            LatLng(0.0, 5.0),
            LatLng(3.0, 5.0)
        )
        .strokeColor(Color.RED)
        .fillColor(Color.BLUE)
)
      

创建空心多边形

可以在一个 Polygon 对象中组合多个路径来创建复杂形状,如填充环,或“圆环”(其中的多边形区域在多边形内呈“岛状”)。复杂形状总是由多个较简单的路径组成。

两个路径必须在同一区域中定义。两个区域中的较大者定义填充区域,它是一个没有附加选项的简单多边形。然后,将第二个路径传递给 addHole() 方法。当较小的第二个路径被较大路径完全包围时,就会产生好像多边形的一部分被去掉的效果。如果该孔与多边形轮廓相交,多边形渲染时将不做任何填充。

以下代码段将创建一个矩形,具有较小的矩形孔。

Java

List<LatLng> hole = Arrays.asList(new LatLng(1, 1),
    new LatLng(1, 2),
    new LatLng(2, 2),
    new LatLng(2, 1),
    new LatLng(1, 1));
Polygon hollowPolygon = map.addPolygon(new PolygonOptions()
    .add(new LatLng(0, 0),
        new LatLng(0, 5),
        new LatLng(3, 5),
        new LatLng(3, 0),
        new LatLng(0, 0))
    .addHole(hole)
    .fillColor(Color.BLUE));
      

Kotlin

val hole = listOf(
    LatLng(1.0, 1.0),
    LatLng(1.0, 2.0),
    LatLng(2.0, 2.0),
    LatLng(2.0, 1.0),
    LatLng(1.0, 1.0)
)
val hollowPolygon = map.addPolygon(
    PolygonOptions()
        .add(
            LatLng(0.0, 0.0),
            LatLng(0.0, 5.0),
            LatLng(3.0, 5.0),
            LatLng(3.0, 0.0),
            LatLng(0.0, 0.0)
        )
        .addHole(hole)
        .fillColor(Color.BLUE)
)
      

多边形事件

默认情况下,多边形无法点击。您可以通过调用 Polygon.setClickable(boolean) 启用和停用可点击性。

使用 OnPolygonClickListener 可以监听可点击的多边形上的点击事件。如需在地图上设置此监听器,请调用 GoogleMap.setOnPolygonClickListener(OnPolygonClickListener)。当用户点击多边形时,您会收到 onPolygonClick(Polygon) 回调。

圆形

除了常规的 Polygon 类之外,Maps API 还包含 Circle 对象的专属类,用以简化其构建过程。

如需构建圆形,您必须指定以下两个属性:

  • center,以 LatLng 形式表示。
  • radius(以米为单位)。

然后便可将圆形定义为地球表面上所有与给定 center 的距离为 radius 米的点的集合。由于 Maps API 使用的墨卡托投影法在平面上呈现球形所用方式的缘故,在地图上靠近赤道的位置,呈现的将是近乎完美的圆,而随着圆的位置远离赤道,则愈发(在屏幕上)呈现为非圆形状。

以下代码段会通过构建 CircleOptions 对象和调用 GoogleMap.addCircle(CircleOptions),为地图添加一个圆形:

Java

// Instantiates a new CircleOptions object and defines the center and radius
CircleOptions circleOptions = new CircleOptions()
    .center(new LatLng(37.4, -122.1))
    .radius(1000); // In meters

// Get back the mutable Circle
Circle circle = map.addCircle(circleOptions);
      

Kotlin

// Instantiates a new CircleOptions object and defines the center and radius
val circleOptions = CircleOptions()
    .center(LatLng(37.4, -122.1))
    .radius(1000.0) // In meters

// Get back the mutable Circle
val circle = map.addCircle(circleOptions)
      

如需在添加圆形后改变其形状,您可以调用 Circle.setRadius()Circle.setCenter() 并提供新值。

在将圆形添加到地图之前和之后,您都可以自定义其外观。如需进一步了解相关信息,请参阅下文有关自定义外观的部分。

圆形事件

默认情况下,圆无法点击。您可以通过使用 CircleOptions.clickable(boolean) 调用 GoogleMap.addCircle() 或调用 Circle.setClickable(boolean) 来启用和停用可点击性。

使用 OnCircleClickListener 可以监听可点击的圆形上的点击事件。如需在地图上设置此监听器,请调用 GoogleMap.setOnCircleClickListener(OnCircleClickListener)

当用户点击某个圆形时,您会收到 onCircleClick(Circle) 回调,如以下代码示例所示:

Java

Circle circle = map.addCircle(new CircleOptions()
    .center(new LatLng(37.4, -122.1))
    .radius(1000)
    .strokeWidth(10)
    .strokeColor(Color.GREEN)
    .fillColor(Color.argb(128, 255, 0, 0))
    .clickable(true));

map.setOnCircleClickListener(new GoogleMap.OnCircleClickListener() {
    @Override
    public void onCircleClick(Circle circle) {
        // Flip the r, g and b components of the circle's stroke color.
        int strokeColor = circle.getStrokeColor() ^ 0x00ffffff;
        circle.setStrokeColor(strokeColor);
    }
});
      

Kotlin

val circle = map.addCircle(
    CircleOptions()
        .center(LatLng(37.4, -122.1))
        .radius(1000.0)
        .strokeWidth(10f)
        .strokeColor(Color.GREEN)
        .fillColor(Color.argb(128, 255, 0, 0))
        .clickable(true)
)
map.setOnCircleClickListener {
    // Flip the r, g and b components of the circle's stroke color.
    val strokeColor = it.strokeColor xor 0x00ffffff
    it.strokeColor = strokeColor
}
      

自定义外观

在向地图添加形状之前和之后,您都可以改变其外观,其中前者是通过在 options 对象上指定所需属性来实现。此外,还公开了所有属性的 getter 方法,以便您轻松获取形状的当前状态。

以下这段代码将会添加一条蓝色的粗多段线,其中包含从墨尔本至珀斯的测地线段。下文将详细介绍这些属性。

Java

Polyline polyline = map.addPolyline(new PolylineOptions()
    .add(new LatLng(-37.81319, 144.96298), new LatLng(-31.95285, 115.85734))
    .width(25)
    .color(Color.BLUE)
    .geodesic(true));
      

Kotlin

val polyline = map.addPolyline(
    PolylineOptions()
        .add(LatLng(-37.81319, 144.96298), LatLng(-31.95285, 115.85734))
        .width(25f)
        .color(Color.BLUE)
        .geodesic(true)
)
      

注意:尽管这些属性大都可以应用于上述的任何一种形状,但某些属性可能不适用于特定形状(例如,多段线不能有填充色,因为它没有内部区域)。

描边颜色

描边颜色是一个 32 位 Alpha-红-绿-蓝 (ARGB) 整数,用于指定形状描边的不透明度和颜色。可通过调用 *Options.strokeColor()(如果是多段线,则调用 PolylineOptions.color())在形状的 options 对象上设置此属性。如果未指定该属性,则默认描边颜色为黑色 (Color.BLACK)。

向地图添加形状后,可通过调用 getStrokeColor()(对于多段线,则是调用 getColor())来获取描边颜色,并可通过调用 setStrokeColor() (setColor() for a polyline) 更改描边颜色。

填充色

填充色仅适用于多边形和圆,不适用于多段线,因为多段线没有指定的内部区域。多边形孔内的区域不属于多边形的内部区域,因此即使设置了填充色,系统也不会为该部分填充颜色。

填充色是一个 32 位 Alpha-红-绿-蓝 (ARGB) 整数,用于指定形状内部的不透明度和颜色。可通过调用 *Options.fillColor() 在形状的 options 对象上设置此属性。如果未指定该属性,则默认描边颜色为透明色 (Color.TRANSPARENT)。

向地图添加形状后,可通过调用 getFillColor() 来获取填充色,并可通过调用 setFillColor() 来更改填充色。

描边宽度

线的描边宽度,表示方法为以像素 (px) 为单位的浮点数。该宽度不会随地图的缩放而缩放(即,形状在所有缩放级别下的描边宽度均相同)。可通过调用 *Options.strokeWidth()(对于多段线,则是调用 PolylineOptions.width())在形状的 option 对象上设置此属性。如果未指定,则默认描边宽度为 10 像素。

向地图添加形状后,可通过调用 getStrokeWidth()(对于多段线,则是调用 getWidth())来获取描边宽度,并可通过调用 setStrokeWidth() (setWidth() for a polyline) 更改描边宽度。

描边图案

默认的描边图案是多段线以及多边形和圆形轮廓的实线。您可以指定 PatternItem 对象的自定义描边图案,其中每个项目都是短划线、点或间隙。

以下示例将多段线的图案设置成了重复的点序列,后跟一个长度为 20 像素的间隙、一个长度为 30 像素的短划线,以及另一个 20 像素的间隙。

Java

List<PatternItem> pattern = Arrays.asList(
    new Dot(), new Gap(20), new Dash(30), new Gap(20));
polyline.setPattern(pattern);
      

Kotlin

val pattern = listOf(
    Dot(), Gap(20F), Dash(30F), Gap(20F)
)
polyline.pattern = pattern
      

图案沿直线重复,从为形状指定的第一个顶点处的第一个图案项开始。

连接类型

对于多段线和多边形的轮廓,您可以指定棱台或圆角 JointType,以替代默认的固定斜角连接。

以下示例将为多段线应用圆角连接:

Java

polyline.setJointType(JointType.ROUND);
      

Kotlin

polyline.jointType = JointType.ROUND
      

连接类型会影响线条的内部转弯。如果该线条的描边图案包含短划线,当短划线横跨连接时,连接类型也适用。连接类型不会影响点,因为它们始终为圆形。

线帽

您可以为多段线的各个端点指定 Cap 样式。选项包括平端(默认)、方端、圆端或自定义位图。在 PolylineOptions.startCapPolylineOptions.endCap 中设置样式,或者使用相应的 getter 和 setter 方法。

以下代码段会为多段线的起点指定一个圆帽。

Java

polyline.setStartCap(new RoundCap());
      

Kotlin

polyline.startCap = RoundCap()
      

以下代码段会为尾帽指定自定义位图:

Java

polyline.setEndCap(
    new CustomCap(BitmapDescriptorFactory.fromResource(R.drawable.arrow), 16));
      

Kotlin

polyline.endCap = CustomCap(BitmapDescriptorFactory.fromResource(R.drawable.arrow), 16F)
      

使用自定义位图时,您应该指定参考描边宽度(以像素为单位)。API 会相应缩放位图。参考描边宽度是您在图片原始尺寸下,为线帽设计位图图片时使用的描边宽度。默认的参考描边宽度为 10 像素。提示:要确定参考描边宽度,请在图片编辑器中以 100% 缩放比例打开位图图片,并参照图片绘制所需的线条描边宽度。

如果您使用 BitmapDescriptorFactory.fromResource() 创建位图,请务必使用密度无关资源 (nodpi)。

测地线段

测地设置只适用于多段线和多边形。它不适用于圆,因为按照定义圆并非线段的集合。

测地设置决定多段线/多边形连续顶点之间线段的绘制方式。测地线段是指沿地球表面(球体)依循最短路径的线段,在采用墨卡托投影法的地图上经常以曲线形式出现。非测地线段在地图上绘制为直线。

可通过调用 *Options.geodesic() 在形状的 option 对象上设置此属性,true 表示应将线段绘制为测地线段,false 表示应将线段绘制为直线。如果未指定该属性,则默认绘制非测地线段 (false)。

向地图添加形状后,可通过调用 isGeodesic() 来获取测地设置,并可通过调用 setGeodesic() 更改测地设置。

Z-index

Z-index 指定该形状相对于地图上其他叠加层(其他形状、地面叠加层和图块叠加层)的叠放顺序。Z-index 较高的叠加层在 Z-index 较低的叠加层之上绘制。Z-index 相同的两个叠加层按任意顺序绘制。

请注意,无论其他叠加层的 Z-index 如何,标记始终在其他叠加层之上绘制。

可通过调用 *Options.zIndex() 在形状的 options 对象上设置此属性。如果未指定该属性,则默认的 Z-index 为 0。向地图添加形状后,可通过调用 getZIndex() 来获取 Z-index,并可通过调用 setZIndex() 更改 Z-index。

显示设置

显示设置指定是否应在地图上绘制形状,其中 true 表示应绘制形状,false 表示不应绘制形状。您可以利用它暂时不在地图上显示某个形状。如需从地图上永久性地移除形状,请针对相应形状调用 remove()

可通过调用 *Options.visible() 在形状的 options 对象上设置此属性。如果未指定该属性,则默认显示设置为 true。向地图添加形状后,可通过调用 isVisible() 来获取显示设置,并可通过调用 setVisible() 更改显示设置。

将数据与形状关联

您可以使用形状的 setTag() 方法存储具有多段线、多边形或圆形的任意数据对象,并使用 getTag() 检索对象。例如,调用 Polyline.setTag() 以存储具有多段线的数据对象,并调用 Polyline.getTag() 来检索数据对象。

以下代码定义了指定多段线的一个任意代码 (A)。

Java

Polyline polyline = map.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)));

polyline.setTag("A");
      

Kotlin

val polyline = map.addPolyline(
    PolylineOptions()
        .clickable(true)
        .add(
            LatLng(-35.016, 143.321),
            LatLng(-34.747, 145.592),
            LatLng(-34.364, 147.891),
            LatLng(-33.501, 150.217),
            LatLng(-32.306, 149.248),
            LatLng(-32.491, 147.309)
        )
)
polyline.tag = "A"
      

以下示例展示了可使用形状存储和检索数据的情形:

  • 您的应用可能适合不同类型的形状,并且您希望在用户点击形状时通过不同方式处理它们。
  • 您可能会与具有唯一记录标识符的系统进行互动,其中形状表示该系统中的特定记录。
  • 形状数据可能会指明用于确定形状 Z-index 的优先级。