轉載請註明出處:http://blog.csdn.net/crazy1235/article/details/43377545
之前寫過一篇關於百度地圖開發的blog,主要介紹了百度地圖的基本地圖的顯示。
詳見:Android百度地圖開發(一)之初體驗
下面來看一下地圖上覆蓋物的添加,以及地理編碼和反地理編碼。
添加覆蓋物
在地圖上添加覆蓋物,一般需要以下幾個步驟:
1. 定義座標點,有可能是一個,有可能是多個(比如:多邊形覆蓋物)。
2. 構造OverlayOptions(地圖覆蓋物選型基類)。
3. 在地圖上添加覆蓋物。
4. 添加相應的監聽事件。
在API中可以看到,BaiDuMap類中有一個方法:
這個方法就是用來在地圖上添加覆蓋物的。此方法需要一個OverlayOptions參數。
進而查看這個類。從API中可以看到這是個抽象類,實例化它就必須用它的子類。api中已經把它的所有子類列出來了,分別是:ArcOptions(弧線形覆蓋物選型類)、CircleOptions(圓形覆蓋物選型類)、DotOptions(圓點覆蓋物選型類)、GroundOverlayOptions(地形圖圖層選型類)、MarkerOptions(標註覆蓋物選型類)、PolygonOptions(多邊形選型類)、PolylineOptions(折線選型類)、TextOptions(文本選型類)。
MarkerOptions--標註覆蓋物。
查看一下API,只需關注返回值是MarkerOptions的方法即可。
此時很簡單就可以構造出一個MarkerOptions對象了。此時需要注意的是:必須添加圖標,不然會報錯!
添加圖標的話,就可以使用icon(BitmapDescriptor icon)這個方法:
BitmapDescriptor是一個bitmap描述信息類。但是在api中沒有看到任何關於構造這個類的方法,只有一個回收對象的方法recycle()。其實在Android中,提到bitmap,一般都會跟一個“xxxFactory” 工廠類聯繫到一起。所以纔想百度api中也會有一個關於構造BitmapDescriptor的工廠類。果不其然,看到了一個BitmapDescriptorFactory這個類。
這個類中包括了很多構造bitmap描述信息類的靜態方法:
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接口中只有一個函數:
此時就需要你添加overlay的返回值(marker)了。實際上BaiDuMap的添加覆蓋物的方法addOverlay(OverlayOptions options)的返回值是Overlay。而Overlay恰好是一個好抽象類。
它的子類分別是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):
這三個方法有點類似於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的方法:
設置多邊形覆蓋物,當然需要多個地圖上的點了。正好有一個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(文字覆蓋物)
設置文字覆蓋物的時候,需要注意文字的顏色,字體大小,位置等屬性:
-
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--地理範圍構造器。
-
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);
彈出窗覆蓋物
在百度地圖上可以添加一種可以彈出的覆蓋物,彈出的窗口布局可以自定義。
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));
-
-