百度地图Marker使用示例

Sep 6,2018   8850 words   32 min

Tags: Android

在之前的博客中,介绍了如何从0开始写一个地图APP,但在那个APP中可用功能太少,只能实现地图的浏览。 所以这篇博客仔细介绍一下SDK中的一个重要组件——Marker。Marker简而言之就是一个放置在地图指定位置的标志。下面会由简单到复杂,介绍和演示Marker的使用。

1.Marker简单示例

关于如何新建项目、添加库、申请KEY之类的这里就不说了,如果不会的话可以看上一篇博客。这里直接从新建好项目之后开始。 首先介绍最简单的Marker(单个、无点击响应事件)的使用方法。这种Marker一般比较适合于只用来展示,无交互的场景。 代码如下。

package com.xuhui.markerexample;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.baidu.mapapi.CoordType;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.*;
import com.baidu.mapapi.model.LatLng;

public class MainActivity extends AppCompatActivity {

    private MapView baiduMapView;
    private BaiduMap baiduMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SDKInitializer.initialize(getApplicationContext());
        SDKInitializer.setCoordType(CoordType.BD09LL);

        setContentView(R.layout.activity_main);
        baiduMapView = (MapView) findViewById(R.id.bmapView);
        // 从MapView中获取地图对象,用于添加删除组件等,对地图进行控制
        baiduMap = baiduMapView.getMap();

        // 添加Marker
        // Step 1 新建LatLng对象用于指定Marker经纬度
        LatLng loc = new LatLng(32.9484, 117.3942);
        // Step 2 新建Descriptor对象用于指定Marker图片
        BitmapDescriptor bd = BitmapDescriptorFactory.fromResource(R.drawable.marker_red);
        // Step 3 对Marker进行位置、图片等设置
        MarkerOptions markerOptions = new MarkerOptions().position(loc).icon(bd).zIndex(9);
        // Step 4 向地图添加Marker
        Marker marker = (Marker) baiduMap.addOverlay(markerOptions);
    }

    @Override
    protected void onResume() {
        super.onResume();
        baiduMapView.onResume();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        baiduMapView.onDestroy();
    }

    @Override
    protected void onPause() {
        super.onPause();
        baiduMapView.onPause();
    }
}

Marker有很多属性可以设置,如是否可拖动等等,更多属性可参考官方文档。 添加Marker主要有四个步骤,即指定Marker经纬度、Marker图像、设置Marker和向地图添加Marker。运行效果如下。 这个Marker只能显示,无法点击交互。

2.可交互Marker

除了显示Marker,我们还可以给Marker添加点击事件,从而实现和用户的交互操作。添加点击事件和其它空间一样,通过注册监听器实现。代码如下。

package com.xuhui.markerexample;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
import com.baidu.mapapi.CoordType;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.*;
import com.baidu.mapapi.model.LatLng;

public class MainActivity extends AppCompatActivity {

    private MapView baiduMapView;
    private BaiduMap baiduMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SDKInitializer.initialize(getApplicationContext());
        SDKInitializer.setCoordType(CoordType.BD09LL);

        setContentView(R.layout.activity_main);
        baiduMapView = (MapView) findViewById(R.id.bmapView);
        // 从MapView中获取地图对象,用于添加删除组件等,对地图进行控制
        baiduMap = baiduMapView.getMap();

        // 添加Marker
        // Step 1 新建LatLng对象用于指定Marker经纬度
        LatLng loc = new LatLng(32.9484, 117.3942);
        // Step 2 新建Descriptor对象用于指定Marker图片
        BitmapDescriptor bd = BitmapDescriptorFactory.fromResource(R.drawable.marker_red);
        // Step 3 对Marker进行位置、图片等设置
        MarkerOptions markerOptions = new MarkerOptions().position(loc).icon(bd).zIndex(9);
        // Step 4 向地图添加Marker
        Marker marker = (Marker) baiduMap.addOverlay(markerOptions);

        // 添加点击事件
        baiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
            @Override
            public boolean onMarkerClick(Marker marker) {
                Toast.makeText(getApplicationContext(),
                        String.valueOf(marker.getPosition().latitude) + "\n"
                                + String.valueOf(marker.getPosition().longitude),
                        Toast.LENGTH_LONG).show();
                return false;
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        baiduMapView.onResume();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        baiduMapView.onDestroy();
    }

    @Override
    protected void onPause() {
        super.onPause();
        baiduMapView.onPause();
    }
}

在地图上点击Marker后,会显示当前Marker的经纬度信息,如下所示。

3.多Marker示例

在实际开发中,很多时候我们不会只显示一个Marker,而是会显示多个Marker,而且还是动态生成Marker。 如读取用户收藏的多个地图点,然后显示在地图上。这里在写代码的时候无法知道到底需要生成多少个Marker,所以是动态的。 对于这种情况可以使用List来解决。将添加Marker的代码独立出来形成一个函数。 然后遍历获得用户坐标点后利用for循环实现Marker的添加,并将添加的多个Marker保存到List中,便于后续管理。代码如下。

package com.xuhui.markerexample;

import android.support.annotation.DrawableRes;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
import com.baidu.mapapi.CoordType;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.*;
import com.baidu.mapapi.model.LatLng;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private MapView baiduMapView;
    private BaiduMap baiduMap;
    // 添加两个list分别用于存放位置和marker
    private List<LatLng> locs = new ArrayList<>();
    private List<Marker> markers = new ArrayList<>();


    private Marker addMarker(BaiduMap baiduMap, LatLng loc, @DrawableRes int ID) {
        BitmapDescriptor bd = BitmapDescriptorFactory.fromResource(ID);
        MarkerOptions markerOptions = new MarkerOptions().position(loc).icon(bd).zIndex(9);
        Marker marker = (Marker) baiduMap.addOverlay(markerOptions);
        return marker;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SDKInitializer.initialize(getApplicationContext());
        SDKInitializer.setCoordType(CoordType.BD09LL);

        setContentView(R.layout.activity_main);
        baiduMapView = (MapView) findViewById(R.id.bmapView);
        baiduMap = baiduMapView.getMap();

        // 模拟生成位置信息
        double lat = 32.9484;
        double lon = 117.3942;
        for (int i = 0; i < 10; i++) {
            LatLng temp = new LatLng(lat, lon);
            locs.add(temp);
            lat += 0.05;
            lon += 0.05;
        }

        // 利用for循环依次添加marker
        for (int i = 0; i < 10; i++) {
            // 可以给不同的marker设置不同的图片资源
            if (i % 2 == 0) {
                addMarker(baiduMap, locs.get(i), R.drawable.marker_red);
            } else {
                addMarker(baiduMap, locs.get(i), R.drawable.marker_blue);
            }

        }

        // 添加点击事件
        baiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
            @Override
            public boolean onMarkerClick(Marker marker) {
                Toast.makeText(getApplicationContext(),
                        String.valueOf(marker.getPosition().latitude) + "\n"
                                + String.valueOf(marker.getPosition().longitude),
                        Toast.LENGTH_LONG).show();
                return false;
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        baiduMapView.onResume();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        baiduMapView.onDestroy();
    }

    @Override
    protected void onPause() {
        super.onPause();
        baiduMapView.onPause();
    }
}

效果如下所示,向地图中添加了多个Marker,并且有相同的点击事件,点击会显示Marker经纬度。

4.返回不同结果的多个Marker

上面说到的例子在实际中还是会有一些问题。想象这样一种情况,用户收藏的点除了经纬度还有其它信息,如名称等。 而通过上面的方式无法获得每一个Marker的“专属信息”,因此当用户点击的时候我们需要知道用户点击的是哪个Marker,对应哪一个专属信息。 对于这种情况,还是用List解决。解决思路是建立两个对应的list,分别存放专属信息和位置信息。 当用户点击Marker的时候,我们判断当前Marker在位置信息list中的索引,然后利用这个索引再去专属信息list中查找,即可获得对应信息了。 现在问题是如何由Maker信息获得Maker索引呢?可以通过计算当前经纬度与list中所有Maker的距离,认为距离最小的那个即为同一个Marker。代码如下。

package com.xuhui.markerexample;

import android.support.annotation.DrawableRes;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
import com.baidu.mapapi.CoordType;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.*;
import com.baidu.mapapi.model.LatLng;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private MapView baiduMapView;
    private BaiduMap baiduMap;
    private List<LatLng> locs = new ArrayList<>();
    private List<Marker> markers = new ArrayList<>();
    private List<String> extra_info = new ArrayList<>();


    private Marker addMarker(BaiduMap baiduMap, LatLng loc, @DrawableRes int ID) {
        BitmapDescriptor bd = BitmapDescriptorFactory.fromResource(ID);
        MarkerOptions markerOptions = new MarkerOptions().position(loc).icon(bd).zIndex(9);
        Marker marker = (Marker) baiduMap.addOverlay(markerOptions);
        return marker;
    }

    // 遍历寻找最近Marker索引
    private int findIndex(List<LatLng> list, LatLng loc) {
        double curLat = loc.latitude;
        double curLon = loc.longitude;
        double tempLat;
        double tempLon;
        double minDis = 100;
        double deltaDis;
        int minIndex = 0;
        for (int i = 0; i < list.size(); i++) {
            tempLat = list.get(i).latitude;
            tempLon = list.get(i).longitude;
            deltaDis = Math.abs(curLat - tempLat) + Math.abs(curLon - tempLon);
            if (deltaDis < minDis) {
                minDis = deltaDis;
                minIndex = i;
            }
        }
        return minIndex;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SDKInitializer.initialize(getApplicationContext());
        SDKInitializer.setCoordType(CoordType.BD09LL);

        setContentView(R.layout.activity_main);
        baiduMapView = (MapView) findViewById(R.id.bmapView);
        baiduMap = baiduMapView.getMap();

        double lat = 32.9484;
        double lon = 117.3942;
        for (int i = 0; i < 10; i++) {
            LatLng temp = new LatLng(lat, lon);
            locs.add(temp);
            lat += 0.05;
            lon += 0.05;
            // 添加附加信息
            extra_info.add("这是第" + String.valueOf(i + 1) + "个Marker\n");
        }

        for (int i = 0; i < 10; i++) {
            if (i % 2 == 0) {
                addMarker(baiduMap, locs.get(i), R.drawable.marker_red);
            } else {
                addMarker(baiduMap, locs.get(i), R.drawable.marker_blue);
            }

        }

        baiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
            @Override
            public boolean onMarkerClick(Marker marker) {
                // 根据Marker位置获得索引信息,由索引信息获得附加信息
                LatLng loc = marker.getPosition();
                int index = findIndex(locs, loc);
                String ext_info = extra_info.get(index);
                Toast.makeText(getApplicationContext(),
                        ext_info
                                + String.valueOf(marker.getPosition().latitude) + "\n"
                                + String.valueOf(marker.getPosition().longitude),
                        Toast.LENGTH_LONG).show();
                return false;
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        baiduMapView.onResume();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        baiduMapView.onDestroy();
    }

    @Override
    protected void onPause() {
        super.onPause();
        baiduMapView.onPause();
    }
}

效果如下所示。点击了第8个Marker后,程序会找到对应索引,并获得对应的附加信息。

以上便是百度地图SDK中Marker的使用介绍。项目还是传到了Github,点击查看。 还是要注意,把清单文件中的KEY替换成你自己的。

本文作者原创,未经许可不得转载,谢谢配合

返回顶部