在之前的博客中,介绍了如何从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替换成你自己的。
本文作者原创,未经许可不得转载,谢谢配合