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

标记

标记用于指示地图上的单个位置。您可以通过更改默认颜色,或用自定义图像替换标记图标来自定义标记。信息窗口可为标记提供其他背景信息。

代码示例

GitHub 上的 ApiDemos 代码库包含一个展示各种标记功能的示例:

简介

标记用于标识地图上的位置。默认标记使用与 Google 地图外观和风格一致的标准图标。可以通过 API 更改图标的颜色、图像或锚点。标记是 Marker 类型的对象,可通过 GoogleMap.addMarker(markerOptions) 方法添加到地图中。

标记设计为可互动。默认情况下,它们会接收 click 事件,且常与事件监听器结合使用,以打开信息窗口。通过将标记的 draggable 属性设置为 true,用户即可更改标记的位置。长按标记即可激活移动标记的功能。

默认情况下,当用户点按标记时,地图工具栏会显示在地图右下角,方便用户快速访问 Google 地图移动应用。您可以停用工具栏。如需了解详情,请参阅控件指南

标记使用入门

本集 Maps Live 介绍了利用 Maps SDK for Android 向地图添加标记的基础知识。

添加标记

以下示例展示了如何向地图添加标记。标记在 10,10 坐标处创建,当用户点击时,它会在信息窗口中显示字符串“Hello world”。

@Override
public void onMapReady(GoogleMap map) {
    map.addMarker(new MarkerOptions()
        .position(new LatLng(10, 10))
        .title("Hello world"));
}

显示与标记有关的其他信息

在用户点按地图上的某个标记时,显示有关地点或位置的其他信息,这是一个常见要求。请参阅有关信息窗口的指南。

将数据与标记关联

您可以通过 Marker.setTag() 使用标记存储任意数据对象,并使用 Marker.getTag() 检索数据对象,如以下代码示例所示:

/**
 * A demo class that stores and retrieves data objects with each marker.
 */
public class MarkerDemoActivity extends FragmentActivity implements
        OnMarkerClickListener,
        OnMapReadyCallback {

    private static final LatLng PERTH = new LatLng(-31.952854, 115.857342);
    private static final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);
    private static final LatLng BRISBANE = new LatLng(-27.47093, 153.0235);

    private Marker mPerth;
    private Marker mSydney;
    private Marker mBrisbane;

    private GoogleMap mMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.marker_demo);

        SupportMapFragment mapFragment =
                (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    /** Called when the map is ready. */
    @Override
    public void onMapReady(GoogleMap map) {
        mMap = map;

        // Add some markers to the map, and add a data object to each marker.
        mPerth = mMap.addMarker(new MarkerOptions()
                .position(PERTH)
                .title("Perth"));
        mPerth.setTag(0);

        mSydney = mMap.addMarker(new MarkerOptions()
                .position(SYDNEY)
                .title("Sydney"));
        mSydney.setTag(0);

        mBrisbane = mMap.addMarker(new MarkerOptions()
                .position(BRISBANE)
                .title("Brisbane"));
        mBrisbane.setTag(0);

        // Set a listener for marker click.
        mMap.setOnMarkerClickListener(this);
    }

    /** Called when the user clicks a marker. */
    @Override
    public boolean onMarkerClick(final Marker marker) {

        // Retrieve the data from the marker.
        Integer clickCount = (Integer) marker.getTag();

        // Check if a click count was set, then display the click count.
        if (clickCount != null) {
            clickCount = clickCount + 1;
            marker.setTag(clickCount);
            Toast.makeText(this,
                           marker.getTitle() +
                           " has been clicked " + clickCount + " times.",
                           Toast.LENGTH_SHORT).show();
        }

        // Return false to indicate that we have not consumed the event and that we wish
        // for the default behavior to occur (which is for the camera to move such that the
        // marker is centered and for the marker's info window to open, if it has one).
        return false;
    }
}

以下示例介绍了可使用标记存储和检索数据的情形:

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

使标记可拖动

将标记添加到地图中后,只要标记的 draggable 属性设为 true,您就可以重新调整其位置。长按标记即可启用拖动功能。手指离开屏幕后,标记会留在手指离开屏幕前的位置。

默认情况下,标记是不可以拖动的。您必须通过在向地图添加标记前使用 MarkerOptions.draggable(boolean),或者在向地图添加标记后使用 Marker.setDraggable(boolean) 明确将标记设置为可拖动。您可以按标记拖动事件中所述监听标记上的拖动事件。

下面这段代码可在澳大利亚珀斯的位置处添加一个可拖动标记。

static final LatLng PERTH = new LatLng(-31.90, 115.86);
Marker perth = mMap.addMarker(new MarkerOptions()
                          .position(PERTH)
                          .draggable(true));

自定义标记

这段视频介绍了利用标记将地图上的位置可视化的方法。

标记可定义在默认图标位置显示的自定义图像。定义图标的操作涉及到设置若干可影响标记视觉行为的属性。

标记支持通过下列属性进行自定义:

Position(必需)
地图上标记位置的 LatLng 值。该值是 Marker 对象唯一的必需属性。
Anchor
图像上将置于标记的 LatLng 位置的点。该点默认为图像底部的中间。
Alpha
设置标记的不透明度。默认值为 1.0。
Title
当用户点按标记时显示在信息窗口内的字符串。
Snippet
显示在标题下方的附加文本。
Icon
取代默认标记图像而显示的位图。
Draggable
如果您想允许用户移动标记,请将其设置为 true。默认值为 false
Visible
设为 false 可使标记不可见。默认值为 true
Flat 或 Billboard 朝向
默认情况下,标记朝向屏幕的相反方向,并且不会随相机旋转或倾斜。Flat 标记与地球表面对齐,将会随相机旋转或倾斜。两种类型的标记都不会随缩放级别而改变大小。如果您想要获得这种效果,请使用 GroundOverlays。
Rotation
标记的朝向,以顺时针度数表示。当标记为 Flat 标记时,默认位置会发生变化。Flat 标记的默认位置指向正北。如果标记不是 Flat 标记,则默认位置为朝上,而且旋转时标记始终朝向镜头。

下面这段代码可创建一个使用默认图标的简单标记。

static final LatLng MELBOURNE = new LatLng(-37.813, 144.962);
Marker melbourne = mMap.addMarker(new MarkerOptions()
                          .position(MELBOURNE));

自定义标记的颜色

通过向 icon() 方法传递 BitmapDescriptor 对象,您可以自定义默认标记图像的颜色。您可以使用 BitmapDescriptorFactory 对象中的一组预定义颜色,或者通过 BitmapDescriptorFactory.defaultMarker(float hue) 方法设置自定义标记颜色。色调是一个介于 0 和 360 之间的值,表示色轮上的点。

static final LatLng MELBOURNE = new LatLng(-37.813, 144.962);
Marker melbourne = mMap.addMarker(new MarkerOptions()
                          .position(MELBOURNE)
                          .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));

自定义标记的不透明度

您可以通过 MarkerOptions.alpha() 方法控制标记的不透明度。您应将 Alpha 指定为介于 0.0 和 1.0 之间的浮点值,其中 0 表示完全透明,而 1 则表示完全不透明。

static final LatLng MELBOURNE = new LatLng(-37.813, 144.962);
Marker melbourne = mMap.addMarker(new MarkerOptions()
                          .position(MELBOURNE)
                          .alpha(0.7f));

自定义标记图像

您可以将默认标记图像替换为自定义标记图像(通常称作图标)。自定义图标始终设置为 BitmapDescriptor,并且可通过 BitmapDescriptorFactory 类中的以下方法之一进行定义。

fromAsset(String assetName)
使用资源目录中的位图图像的名称创建自定义标记。
fromBitmap(Bitmap image)
使用位图图像创建自定义标记。
fromFile(String fileName)
使用位于内部存储中的位图图像文件的名称创建自定义图标。
fromPath(String absolutePath)
使用位图图像的绝对文件路径创建自定义标记。
fromResource(int resourceId)
使用位图图像的资源 ID 创建自定义标记。

下面这段代码可创建一个使用自定义图标的标记。

  private static final LatLng MELBOURNE = new LatLng(-37.813, 144.962);
  private Marker melbourne = mMap.addMarker(new MarkerOptions()
                            .position(MELBOURNE)
                            .title("Melbourne")
                            .snippet("Population: 4,137,400")
                            .icon(BitmapDescriptorFactory.fromResource(R.drawable.arrow)));

将标记平面化

标记图标通常以屏幕为参照物进行绘制;旋转、倾斜或缩放地图均不会改变标记的朝向。您可以将标记的朝向设置为平贴地球表面。采用这种朝向的标记将随地图的旋转而旋转,并在地图倾斜时改变视角。Flat 标记将在地图缩放时保持大小不变。

如需更改标记的朝向,请将标记的 flat 属性设置为 true

static final LatLng PERTH = new LatLng(-31.90, 115.86);
Marker perth = mMap.addMarker(new MarkerOptions()
                          .position(PERTH)
                          .flat(true));

旋转标记

您可以通过 Marker.setRotation() 方法让标记围绕其锚点旋转。旋转以与默认位置所呈顺时针角度来表示。当地图上的标记为 Flat 标记时,默认位置为指向北方。如果标记不是 Flat 标记,则默认位置为朝上,而且旋转时标记始终朝向镜头。

以下示例代码可将标记旋转 90°。将锚点设置为 0.5,0.5 可使标记围绕其中心而不是底部旋转。

static final LatLng PERTH = new LatLng(-31.90, 115.86);
Marker perth = mMap.addMarker(new MarkerOptions()
                          .position(PERTH)
                          .anchor(0.5,0.5)
                          .rotation(90.0));

标记 Z-index

Z-index 指定此标记相对于地图上其他标记的叠放顺序。Z-index 较高的标记绘制在 Z-index 较低的标记之上。默认 Z-index 值为 0

通过调用 MarkerOptions.zIndex() 在标记的选项对象上设置 Z-index,如以下代码段所示:

@Override
public void onMapReady(GoogleMap map) {
    map.addMarker(new MarkerOptions()
        .position(new LatLng(10, 10))
        .title("Marker z1")
        .zIndex(1.0f));
}

您可以通过调用 Marker.getZIndex() 获取标记的 Z-index,并且可以通过调用 Marker.setZIndex() 对其进行更改。

标记始终在图块图层和其他非标记叠加层(地面叠加层、多段线、多边形和其他形状)之上绘制,而不考虑其他叠加层的 Z-index 值。事实上,与其他叠加层相比,可将标记视为位于单独的 Z-index 组中。

请参阅下文,了解 Z-index 对点击事件的影响

处理标记事件

您可以使用 Maps API 监听和响应标记事件。如需监听这些事件,您必须在标记所属的 GoogleMap 对象上设置相应的监听器。当地图上的某个标记发生事件时,系统将调用监听器的回调并传递相应 Marker 对象作为参数。如需将此 Marker 对象和您对 Marker 对象的引用进行比较,您必须使用 equals(),而非 ==

您可以监听以下事件:

标记点击事件

OnMarkerClickListener 可用于监听标记上的点击事件。如需在地图上设置此监听器,请调用 GoogleMap.setOnMarkerClickListener(OnMarkerClickListener)。当用户点击标记时,系统会调用 onMarkerClick(Marker),并以参数的形式传递标记。此方法会返回一个布尔值,指示您是否使用了该事件(即您想禁止默认行为)。如果它返回 false,则除了自定义行为外,还会发生默认行为。默认情况下,用户点击标记时,系统会显示相应的信息窗口(如果有),并移动相机,使标记位于地图中心。

Z-index 对点击事件的影响:

  • 当用户点击标记的聚类时,将触发 Z-index 最高的标记的点击事件。
  • 每个点击至多可触发一个事件。换句话说,点击不会传递到具有较低 Z-index 值的标记或其他叠加层。
  • 点击标记的聚类会导致后续点击在聚类中循环,从而依次选择每个标记。循环的顺序优先考虑 Z-index,然后才考虑点击点的距离。
  • 如果用户点击超出聚类的距离,则 API 将重新计算此聚类,并重置点击循环的状态,以便从头开始循环。
  • 点击事件依次作用于聚类中的每个标记,再作用于其他形状和叠加层,然后重新开始循环。
  • 事实上,与其他叠加层或形状(多段线、多边形、圆形和/或地面叠加层)相比,可将标记视为位于单独的 Z-index 组中,而不考虑其他叠加层的 Z-index 值。如果多个标记、叠加层或形状在彼此的顶部叠加,则点击事件首先在标记聚类中循环,然后根据其他可点击的叠加层或形状的 Z-index 值触发点击事件。

标记拖动事件

OnMarkerDragListener 可用于监听标记上的拖动事件。如需在地图上设置此监听器,请调用 GoogleMap.setOnMarkerDragListener。如需拖动标记,用户必须长按标记。用户的手指离开屏幕后,标记会留在手指离开屏幕前的位置。用户拖动标记时,系统会先调用 onMarkerDragStart(Marker)。如果用户正在拖动标记,则系统会不断调用 onMarkerDrag(Marker)。拖动结束时,系统会调用 onMarkerDragEnd(Marker)。您随时可以通过调用 Marker.getPosition() 获取标记的位置。