Android百度地圖開發(2)

轉載請註明出處: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添加一個圖片。

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. // 定義marker座標點  
  2.         LatLng point = new LatLng(latitude, longitude);  
  3.   
  4.         // 構建markerOption,用於在地圖上添加marker  
  5.         OverlayOptions options = new MarkerOptions()//  
  6.                 .position(point)// 設置marker的位置  
  7.                 .icon(bitmap)// 設置marker的圖標  
  8.                 .zIndex(9)// 設置marker的所在層級  
  9.                 .draggable(true);// 設置手勢拖拽  
  10.         // 在地圖上添加marker,並顯示  
  11.         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的子類一一對應。

    下面是點擊事件的代碼:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. bdMap.setOnMapClickListener(new OnMapClickListener() {  
  2.   
  3.             @Override  
  4.             public boolean onMapPoiClick(MapPoi arg0) {  
  5.                 return false;  
  6.             }  
  7.   
  8.             @Override  
  9.             public void onMapClick(LatLng latLng) {  
  10.                 displayInfoWindow(latLng);  
  11.             }  
  12.         });  
    此時有一個問題,我得到了LatLng地理座標這個對象了,怎麼得到正常的地理信息呢(xx省xx市)?不要着急,慢慢往後看,反地理編碼會解決這個問題的!
    下面看一下,拖拽事件(onMarkerDragListener):


    這三個方法有點類似於onTouch方法(按下,拖動,擡起)。

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. bdMap.setOnMarkerDragListener(new OnMarkerDragListener() {  
  2.             @Override  
  3.             public void onMarkerDragStart(Marker arg0) {  
  4.   
  5.             }  
  6.   
  7.             @Override  
  8.             public void onMarkerDragEnd(Marker arg0) {  
  9.                 Toast.makeText(  
  10.                         MainActivity.this,  
  11.                         "拖拽結束,新位置:" + arg0.getPosition().latitude + ", "  
  12.                                 + arg0.getPosition().longitude,  
  13.                         Toast.LENGTH_LONG).show();  
  14.                 reverseGeoCode(arg0.getPosition());  
  15.             }  
  16.   
  17.             @Override  
  18.             public void onMarkerDrag(Marker arg0) {  
  19.   
  20.             }  
  21.         });  
    此時需要注意:拖拽事件,需要長按才能響應。

PolygonOptions(多邊形覆蓋)

    繼續查看API,查看這個類中的返回值是PolygonOptions的方法:



    設置多邊形覆蓋物,當然需要多個地圖上的點了。正好有一個points(List<LatLng> points)的方法用於設置多邊形座標點列表。OK,此時構造出一個PolygonOptions就不難了。

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. LatLng pt1 = new LatLng(latitude + 0.02, longitude);  
  2.         LatLng pt2 = new LatLng(latitude, longitude - 0.03);  
  3.         LatLng pt3 = new LatLng(latitude - 0.02, longitude - 0.01);  
  4.         LatLng pt4 = new LatLng(latitude - 0.02, longitude + 0.01);  
  5.         LatLng pt5 = new LatLng(latitude, longitude + 0.03);  
  6.         List<LatLng> points = new ArrayList<LatLng>();  
  7.         points.add(pt1);  
  8.         points.add(pt2);  
  9.         points.add(pt3);  
  10.         points.add(pt4);  
  11.         points.add(pt5);  
  12.         //  
  13.         PolygonOptions polygonOptions = new PolygonOptions();  
  14.         polygonOptions.points(points);  
  15.         polygonOptions.fillColor(0xAAFFFF00);  
  16.         polygonOptions.stroke(new Stroke(20xAA00FF00));  
  17.         Overlay polygon = bdMap.addOverlay(polygonOptions);  

TextOptions(文字覆蓋物)

    設置文字覆蓋物的時候,需要注意文字的顏色,字體大小,位置等屬性:



[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. LatLng latLng = new LatLng(latitude, longitude);  
  2.         TextOptions textOptions = new TextOptions();  
  3.         textOptions.bgColor(0xAAFFFF00)  //設置文字覆蓋物背景顏色  
  4.             .fontSize(28)  //設置字體大小  
  5.             .fontColor(0xFFFF00FF)// 設置字體顏色  
  6.             .text("我在這裏啊!!!!")  //文字內容  
  7.             .rotate(-30)  //設置文字的旋轉角度  
  8.             .position(latLng);// 設置位置  
  9.         bdMap.addOverlay(textOptions);  

GroundOverlay(地形圖圖層覆蓋物)

    地形圖圖層可以跟隨地圖進行平移,伸縮等變換,位於底圖和標註圖層之家,不會遮擋地圖標註的信息。定義這個覆蓋物的時候,需要指定寬高。這裏百度API提供了兩種方法:

1. 指定一個地理座標(LatLng),在用dimensions方法來指定寬度和高度。

2. 使用positionFromBounds(LagLngBounds bounds)方法。LatLngBounds方法表示一個地理範圍,包括一個東北角座標和一個西南角座標,這樣也能確定一個矩形。
    在LatLng中有一個靜態內部類Builder--地理範圍構造器。


[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. LatLng southwest = new LatLng(latitude - 0.01, longitude - 0.012);//西南  
  2.         LatLng northeast = new LatLng(latitude + 0.01, longitude + 0.012);//東北  
  3.         LatLngBounds bounds = new LatLngBounds.Builder().include(southwest)  
  4.                 .include(northeast).build();//得到一個地理範圍對象  
  5.         BitmapDescriptor bitmap2 = BitmapDescriptorFactory  
  6.             .fromResource(R.drawable.csdn_blog);  
  7.         GroundOverlayOptions groundOverlayOptions = new GroundOverlayOptions();  
  8.         groundOverlayOptions.image(bitmap2);//顯示的圖片  
  9.         groundOverlayOptions.positionFromBounds(bounds);//顯示的位置  
  10.         groundOverlayOptions.transparency(0.7f);//顯示的透明度  
  11.         bdMap.addOverlay(groundOverlayOptions);  

PolylineOptions(折線覆蓋物)

    添加折線與添加多邊形的方法大致相同。這裏就不多贅述了。

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. CircleOptions circleOptions = new CircleOptions();  
  2.         circleOptions.center(new LatLng(latitude, longitude));//設置圓心座標  
  3.         circleOptions.fillColor(0XFFfaa755);//圓的填充顏色  
  4.         circleOptions.radius(150);//設置半徑  
  5.         circleOptions.stroke(new Stroke(50xAA00FF00));//設置邊框  
  6.         bdMap.addOverlay(circleOptions);  

DotOptions(圓點覆蓋物)

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. DotOptions dotOptions = new DotOptions();  
  2.         dotOptions.center(new LatLng(latitude, longitude));//設置圓心座標  
  3.         dotOptions.color(0XFFfaa755);//顏色  
  4.         dotOptions.radius(25);//設置半徑  
  5.         bdMap.addOverlay(dotOptions);  

CircleOptions(圓形(空心)覆蓋物)

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. CircleOptions circleOptions = new CircleOptions();  
  2.         circleOptions.center(new LatLng(latitude, longitude));//設置圓心座標  
  3.         circleOptions.fillColor(0XFFfaa755);//圓的填充顏色  
  4.         circleOptions.radius(150);//設置半徑  
  5.         circleOptions.stroke(new Stroke(50xAA00FF00));//設置邊框  
  6.         bdMap.addOverlay(circleOptions);  

ArcOptions(弧線覆蓋物)

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. LatLng pt1 = new LatLng(latitude, longitude - 0.01);  
  2.         LatLng pt2 = new LatLng(latitude - 0.01, longitude - 0.01);  
  3.         LatLng pt3 = new LatLng(latitude, longitude + 0.01);  
  4.         ArcOptions arcOptions = new ArcOptions();  
  5.         arcOptions.points(pt1, pt2, pt3);//設置弧線的起點、中點、終點座標  
  6.         arcOptions.width(5);//線寬  
  7.         arcOptions.color(0xFF000000);  
  8.         bdMap.addOverlay(arcOptions);  

彈出窗覆蓋物

    在百度地圖上可以添加一種可以彈出的覆蓋物,彈出的窗口布局可以自定義。



    API中說的很清楚,第二個構造函數,只能做顯示用,沒有響應事件。通過第一個構造方法,可以添加點擊事件。

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. /** 
  2.      * 顯示彈出窗口覆蓋物 
  3.      */  
  4.     private void displayInfoWindow(final LatLng latLng) {  
  5.         // 創建infowindow展示的view  
  6.         Button btn = new Button(getApplicationContext());  
  7.         btn.setBackgroundResource(R.drawable.popup);  
  8.         btn.setText("點我點我~");  
  9.         BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory  
  10.                 .fromView(btn);  
  11.         // infowindow點擊事件  
  12.         OnInfoWindowClickListener infoWindowClickListener = new OnInfoWindowClickListener() {  
  13.             @Override  
  14.             public void onInfoWindowClick() {  
  15.                 reverseGeoCode(latLng);  
  16.                 //隱藏InfoWindow  
  17.                 bdMap.hideInfoWindow();  
  18.             }  
  19.         };  
  20.         // 創建infowindow  
  21.         InfoWindow infoWindow = new InfoWindow(bitmapDescriptor, latLng, -47,  
  22.                 infoWindowClickListener);  
  23.   
  24.         // 顯示InfoWindow  
  25.         bdMap.showInfoWindow(infoWindow);  
  26.     }  

地理編碼與反地理編碼

    地理編碼指的是將地理信息轉化成座標關係的過程。分爲正向的和反向的編碼。

正向的就是指將地址信息轉成座標點的過程。比如:北京市天安門--> (123.23111, 123.23231)(我瞎寫的)。反地理編碼就是將地理座標轉換成具體的地址信息,通過百度的座標定位引擎,插敘出座標對應的物體所在的行政區劃、街道等信息。

    所以我們,在地圖上點擊的時候,或者拖動marker的時候得到的LatLng對象,就可以通過反地理編碼得到具體的地址了。

    實現起來也比較簡單:

[java] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. // 創建地理編碼檢索實例  
  2.         GeoCoder geoCoder = GeoCoder.newInstance();  
  3.         //  
  4.         OnGetGeoCoderResultListener listener = new OnGetGeoCoderResultListener() {  
  5.             // 反地理編碼查詢結果回調函數  
  6.             @Override  
  7.             public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {  
  8.                 if (result == null  
  9.                         || result.error != SearchResult.ERRORNO.NO_ERROR) {  
  10.                     // 沒有檢測到結果  
  11.                     Toast.makeText(MainActivity.this"抱歉,未能找到結果",  
  12.                             Toast.LENGTH_LONG).show();  
  13.                 }  
  14.                 Toast.makeText(MainActivity.this,  
  15.                         "位置:" + result.getAddress(), Toast.LENGTH_LONG)  
  16.                         .show();  
  17.             }  
  18.   
  19.             // 地理編碼查詢結果回調函數  
  20.             @Override  
  21.             public void onGetGeoCodeResult(GeoCodeResult result) {  
  22.                 if (result == null  
  23.                         || result.error != SearchResult.ERRORNO.NO_ERROR) {  
  24.                     // 沒有檢測到結果  
  25.                 }  
  26.             }  
  27.         };  
  28.         // 設置地理編碼檢索監聽者  
  29.         geoCoder.setOnGetGeoCodeResultListener(listener);  
  30.         //  
  31.         geoCoder.reverseGeoCode(new ReverseGeoCodeOption().location(latLng));  
  32.         // 釋放地理編碼檢索實例  
  33.         // geoCoder.destroy();  
發佈了42 篇原創文章 · 獲贊 50 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章