转载请注明出处:http://blog.csdn.net/crazy1235/article/details/43377545
之前写过一篇关于百度地图开发的blog,主要介绍了百度地图的基本地图的显示。
详见:Android百度地图开发(一)之初体验
下面来看一下地图上覆盖物的添加,以及地理编码和反地理编码。
添加覆盖物
在地图上添加覆盖物,一般需要以下几个步骤:
1. 定义坐标点,有可能是一个,有可能是多个(比如:多边形覆盖物)。
2. 构造OverlayOptions(地图覆盖物选型基类)。
3. 在地图上添加覆盖物。
4. 添加相应的监听事件。
在API中可以看到,BaiDuMap类中有一个方法:![](https://img-blog.csdn.net/20150201225232231)
这个方法就是用来在地图上添加覆盖物的。此方法需要一个OverlayOptions参数。
进而查看这个类。从API中可以看到这是个抽象类,实例化它就必须用它的子类。api中已经把它的所有子类列出来了,分别是:ArcOptions(弧线形覆盖物选型类)、CircleOptions(圆形覆盖物选型类)、DotOptions(圆点覆盖物选型类)、GroundOverlayOptions(地形图图层选型类)、MarkerOptions(标注覆盖物选型类)、PolygonOptions(多边形选型类)、PolylineOptions(折线选型类)、TextOptions(文本选型类)。
MarkerOptions--标注覆盖物。
查看一下API,只需关注返回值是MarkerOptions的方法即可。
![](https://img-blog.csdn.net/20150201230132522)
![](https://img-blog.csdn.net/20150201230213513)
![](https://img-blog.csdn.net/20150201230235931)
此时很简单就可以构造出一个MarkerOptions对象了。此时需要注意的是:必须添加图标,不然会报错!
![](https://img-blog.csdn.net/20150201230408507?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY3JhenkxMjM1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
添加图标的话,就可以使用icon(BitmapDescriptor icon)这个方法:
![](https://img-blog.csdn.net/20150201230751909?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY3JhenkxMjM1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
BitmapDescriptor是一个bitmap描述信息类。但是在api中没有看到任何关于构造这个类的方法,只有一个回收对象的方法recycle()。其实在Android中,提到bitmap,一般都会跟一个“xxxFactory” 工厂类联系到一起。所以才想百度api中也会有一个关于构造BitmapDescriptor的工厂类。果不其然,看到了一个BitmapDescriptorFactory这个类。 ![](https://img-blog.csdn.net/20150201231225128)
这个类中包括了很多构造bitmap描述信息类的静态方法:
![](https://img-blog.csdn.net/20150201231338167)
OK,有了这一步,就可以构造出一个BitmapDescriptor对象了,进而对marker添加一个图片。
-
- LatLng point = new LatLng(latitude, longitude);
-
-
- OverlayOptions options = new MarkerOptions()
- .position(point)
- .icon(bitmap)
- .zIndex(9)
- .draggable(true);
-
- marker1 = (Marker) bdMap.addOverlay(options);
接下来对marker添加监听事件。一开始我猜想,应该是MarkerOptions这个类中有一个 “setOnxxx” 这种形式的方法来绑定事件,但是没有找到。最后还是在BaiDuMap这个类下面找到了两个静态的接口。
先看一下点击事件。onMarkerClickListener接口中只有一个函数:
![](https://img-blog.csdn.net/20150201232043518)
此时就需要你添加overlay的返回值(marker)了。实际上BaiDuMap的添加覆盖物的方法addOverlay(OverlayOptions options)的返回值是Overlay。而Overlay恰好是一个好抽象类。
![](https://img-blog.csdn.net/20150201232251506)
它的子类分别是Arc、Circle、Dot、GroundOverlay、Marker、Polygon、Polyline、Text。
正好与verlayOption的子类一一对应。
下面是点击事件的代码:
- bdMap.setOnMapClickListener(new OnMapClickListener() {
-
- @Override
- public boolean onMapPoiClick(MapPoi arg0) {
- return false;
- }
-
- @Override
- public void onMapClick(LatLng latLng) {
- displayInfoWindow(latLng);
- }
- });
此时有一个问题,我得到了LatLng地理坐标这个对象了,怎么得到正常的地理信息呢(xx省xx市)?不要着急,慢慢往后看,
反地理编码
会解决这个问题的!
下面看一下,
拖拽事件
(onMarkerDragListener):
![](https://img-blog.csdn.net/20150201232948286)
这三个方法有点类似于onTouch方法(按下,拖动,抬起)。
- bdMap.setOnMarkerDragListener(new OnMarkerDragListener() {
- @Override
- public void onMarkerDragStart(Marker arg0) {
-
- }
-
- @Override
- public void onMarkerDragEnd(Marker arg0) {
- Toast.makeText(
- MainActivity.this,
- "拖拽结束,新位置:" + arg0.getPosition().latitude + ", "
- + arg0.getPosition().longitude,
- Toast.LENGTH_LONG).show();
- reverseGeoCode(arg0.getPosition());
- }
-
- @Override
- public void onMarkerDrag(Marker arg0) {
-
- }
- });
此时需要注意:拖拽事件,需要长按才能响应。
PolygonOptions(多边形覆盖)
继续查看API,查看这个类中的返回值是PolygonOptions的方法:
![](https://img-blog.csdn.net/20150201233404595)
![](https://img-blog.csdn.net/20150201233412946)
设置多边形覆盖物,当然需要多个地图上的点了。正好有一个points(List<LatLng> points)的方法用于设置多边形坐标点列表。OK,此时构造出一个PolygonOptions就不难了。
- LatLng pt1 = new LatLng(latitude + 0.02, longitude);
- LatLng pt2 = new LatLng(latitude, longitude - 0.03);
- LatLng pt3 = new LatLng(latitude - 0.02, longitude - 0.01);
- LatLng pt4 = new LatLng(latitude - 0.02, longitude + 0.01);
- LatLng pt5 = new LatLng(latitude, longitude + 0.03);
- List<LatLng> points = new ArrayList<LatLng>();
- points.add(pt1);
- points.add(pt2);
- points.add(pt3);
- points.add(pt4);
- points.add(pt5);
-
- PolygonOptions polygonOptions = new PolygonOptions();
- polygonOptions.points(points);
- polygonOptions.fillColor(0xAAFFFF00);
- polygonOptions.stroke(new Stroke(2, 0xAA00FF00));
- Overlay polygon = bdMap.addOverlay(polygonOptions);
TextOptions(文字覆盖物)
设置文字覆盖物的时候,需要注意文字的颜色,字体大小,位置等属性:
![](https://img-blog.csdn.net/20150201233832422)
![](https://img-blog.csdn.net/20150201233848880)
- LatLng latLng = new LatLng(latitude, longitude);
- TextOptions textOptions = new TextOptions();
- textOptions.bgColor(0xAAFFFF00)
- .fontSize(28)
- .fontColor(0xFFFF00FF)
- .text("我在这里啊!!!!")
- .rotate(-30)
- .position(latLng);
- bdMap.addOverlay(textOptions);
GroundOverlay(地形图图层覆盖物)
地形图图层可以跟随地图进行平移,伸缩等变换,位于底图和标注图层之家,不会遮挡地图标注的信息。定义这个覆盖物的时候,需要指定宽高。这里百度API提供了两种方法:
1. 指定一个地理坐标(LatLng),在用dimensions方法来指定宽度和高度。
2. 使用positionFromBounds(LagLngBounds bounds)方法。LatLngBounds方法表示一个地理范围,包括一个东北角坐标和一个西南角坐标,这样也能确定一个矩形。
在LatLng中有一个静态内部类Builder--地理范围构造器。
![](https://img-blog.csdn.net/20150201234451762)
- LatLng southwest = new LatLng(latitude - 0.01, longitude - 0.012);
- LatLng northeast = new LatLng(latitude + 0.01, longitude + 0.012);
- LatLngBounds bounds = new LatLngBounds.Builder().include(southwest)
- .include(northeast).build();
- BitmapDescriptor bitmap2 = BitmapDescriptorFactory
- .fromResource(R.drawable.csdn_blog);
- GroundOverlayOptions groundOverlayOptions = new GroundOverlayOptions();
- groundOverlayOptions.image(bitmap2);
- groundOverlayOptions.positionFromBounds(bounds);
- groundOverlayOptions.transparency(0.7f);
- bdMap.addOverlay(groundOverlayOptions);
PolylineOptions(折线覆盖物)
添加折线与添加多边形的方法大致相同。这里就不多赘述了。
- CircleOptions circleOptions = new CircleOptions();
- circleOptions.center(new LatLng(latitude, longitude));
- circleOptions.fillColor(0XFFfaa755);
- circleOptions.radius(150);
- circleOptions.stroke(new Stroke(5, 0xAA00FF00));
- bdMap.addOverlay(circleOptions);
DotOptions(圆点覆盖物)
- DotOptions dotOptions = new DotOptions();
- dotOptions.center(new LatLng(latitude, longitude));
- dotOptions.color(0XFFfaa755);
- dotOptions.radius(25);
- bdMap.addOverlay(dotOptions);
CircleOptions(圆形(空心)覆盖物)
- CircleOptions circleOptions = new CircleOptions();
- circleOptions.center(new LatLng(latitude, longitude));
- circleOptions.fillColor(0XFFfaa755);
- circleOptions.radius(150);
- circleOptions.stroke(new Stroke(5, 0xAA00FF00));
- bdMap.addOverlay(circleOptions);
ArcOptions(弧线覆盖物)
- LatLng pt1 = new LatLng(latitude, longitude - 0.01);
- LatLng pt2 = new LatLng(latitude - 0.01, longitude - 0.01);
- LatLng pt3 = new LatLng(latitude, longitude + 0.01);
- ArcOptions arcOptions = new ArcOptions();
- arcOptions.points(pt1, pt2, pt3);
- arcOptions.width(5);
- arcOptions.color(0xFF000000);
- bdMap.addOverlay(arcOptions);
弹出窗覆盖物
在百度地图上可以添加一种可以弹出的覆盖物,弹出的窗口布局可以自定义。
![](https://img-blog.csdn.net/20150201235116932)
![](https://img-blog.csdn.net/20150201235146738)
API中说的很清楚,第二个构造函数,只能做显示用,没有响应事件。通过第一个构造方法,可以添加点击事件。
-
-
-
- private void displayInfoWindow(final LatLng latLng) {
-
- Button btn = new Button(getApplicationContext());
- btn.setBackgroundResource(R.drawable.popup);
- btn.setText("点我点我~");
- BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory
- .fromView(btn);
-
- OnInfoWindowClickListener infoWindowClickListener = new OnInfoWindowClickListener() {
- @Override
- public void onInfoWindowClick() {
- reverseGeoCode(latLng);
-
- bdMap.hideInfoWindow();
- }
- };
-
- InfoWindow infoWindow = new InfoWindow(bitmapDescriptor, latLng, -47,
- infoWindowClickListener);
-
-
- bdMap.showInfoWindow(infoWindow);
- }
地理编码与反地理编码
地理编码指的是将地理信息转化成坐标关系的过程。分为正向的和反向的编码。
正向的就是指将地址信息转成坐标点的过程。比如:北京市天安门--> (123.23111, 123.23231)(我瞎写的)。反地理编码就是将地理坐标转换成具体的地址信息,通过百度的坐标定位引擎,插叙出坐标对应的物体所在的行政区划、街道等信息。
所以我们,在地图上点击的时候,或者拖动marker的时候得到的LatLng对象,就可以通过反地理编码得到具体的地址了。
实现起来也比较简单:
-
- GeoCoder geoCoder = GeoCoder.newInstance();
-
- OnGetGeoCoderResultListener listener = new OnGetGeoCoderResultListener() {
-
- @Override
- public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {
- if (result == null
- || result.error != SearchResult.ERRORNO.NO_ERROR) {
-
- Toast.makeText(MainActivity.this, "抱歉,未能找到结果",
- Toast.LENGTH_LONG).show();
- }
- Toast.makeText(MainActivity.this,
- "位置:" + result.getAddress(), Toast.LENGTH_LONG)
- .show();
- }
-
-
- @Override
- public void onGetGeoCodeResult(GeoCodeResult result) {
- if (result == null
- || result.error != SearchResult.ERRORNO.NO_ERROR) {
-
- }
- }
- };
-
- geoCoder.setOnGetGeoCodeResultListener(listener);
-
- geoCoder.reverseGeoCode(new ReverseGeoCodeOption().location(latLng));
-
-