之前我們講了怎麼在百度地圖上設置Marker(如A點。。) 和彈出框(跟隨Marker的,Marker移動的時候也是會跟着移動的),接着又覺得百度地圖自帶的放大縮小不(fei)是(chang)很(de)漂(chou)亮,我們自定義了放大縮小的控件,本篇我們將製作類似百度地圖API製作類似百度地圖的公交/駕車/行走/查詢界面並實現簡單的路線規劃功能。
先來張截圖:
這個界面的實現其實是使用的SlidingUpPanelLayout 開源庫從而使得可以跟隨手指下拉上劃:
其實佈局也沒什麼好講的,自己到百度地圖的APK包裏扒拉扒拉圖片就都有了,哈哈
<?xml version="1.0" encoding="utf-8"?>
<com.jsbtclient.cusViews.SlidingUpPanelLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:sothree="http://schemas.android.com/apk/res-auto"
android:id="@+id/map_sliding_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom"
sothree:umanoPanelHeight="60dp"
sothree:umanoShadowHeight="4dp" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.baidu.mapapi.map.MapView
android:id="@+id/map_mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:apiKey="vNQtC8sQSODsLGBk01HYaBQt"
android:clickable="true" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true" >
<com.jsbtclient.cusViews.ZoomControlView
android:id="@+id/map_zoomcontrol"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginBottom="20dp"
android:layout_marginRight="15dp" >
</com.jsbtclient.cusViews.ZoomControlView>
<ImageView
android:id="@+id/map_relocation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|top"
android:layout_marginLeft="15dp"
android:layout_marginTop="5dp"
android:background="@drawable/map_relocation_bg"
android:src="@drawable/baidu_map_relocation" />
</FrameLayout>
</RelativeLayout>
<LinearLayout
android:id="@+id/map_slidePanel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp" >
<LinearLayout
android:id="@+id/slidingdrawer_menu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp" >
<ImageView
android:id="@+id/map_route_bus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@drawable/map_route_bus_selector" />
<ImageView
android:id="@+id/map_route_car"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@drawable/map_route_car_selector" />
<ImageView
android:id="@+id/map_route_walk"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@drawable/map_route_walk_selector" />
<TextView
android:id="@+id/map_route_search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:text="@string/map_route_search"
android:textColor="@color/call_fragment_bg_color"
android:textSize="16sp" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="0.1dp"
android:background="@color/lightgray" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/white_shadow_bg"
android:orientation="horizontal"
android:padding="10dp" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@drawable/map_route_start" />
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@drawable/map_route_end" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="8"
android:orientation="vertical"
android:padding="10dp" >
<EditText
android:id="@+id/map_my_address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@null"
android:text="@string/map_my_address"
android:textColor="@color/lightgrey"
android:textSize="16sp" />
<View
android:layout_width="match_parent"
android:layout_height="0.1dp"
android:layout_marginBottom="20dp"
android:layout_marginTop="20dp"
android:background="@color/lightgray" />
<EditText
android:id="@+id/map_target_address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@null"
android:text="@string/map_company_address"
android:textColor="@color/call_fragment_bg_color"
android:textSize="16sp" />
</LinearLayout>
<ImageView
android:id="@+id/map_route_exchange"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:src="@drawable/route_exchange" />
</LinearLayout>
</LinearLayout>
</com.jsbtclient.cusViews.SlidingUpPanelLayout>
UI上的事就不重點說了,功能實現纔是重點:
我們來理一下思路用戶當前的位置是使用百度地圖定位獲取的,而目標位置則應該是用戶自己輸入的,我這裏的實現比較簡單,目的地或者出發地點是固定的就是公司地址,
但是原理是相同的只不過少一次網絡請求而已。 現在假設用戶目的地是指定地點(已知經緯度),那麼我們需要查詢的就是用戶當前的位置,所以首先要定位用戶當前位置。
/**
* 開啓定位,回調接口爲MyLocationListener類 /接口
*/
private void StartLocation()
{
LocationClientOption option = new LocationClientOption();
option.setLocationMode(LocationMode.Hight_Accuracy);//設置定位模式
option.setCoorType("gcj02");//返回的定位結果是百度經緯度
option.setScanSpan(1000);//設置發起定位請求的間隔時間爲1000ms
option.setIsNeedAddress(true); //是否需要返回地址
mLocationClient.setLocOption(option);
mLocationClient.start();//發起定位請求
}
接着看回調接口:
/**
* 定位回調監聽
*
*/
public class MyLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location)
{
//回調返回對象對象裏包含多個屬性,這裏我們只需要經緯度
userLatLng = new LatLng(location.getLatitude(), location.getLongitude());
//這句代碼可以忽略,我不知道定位可以拿到具體的地址,所以使用了 詳細地址與經緯度轉化的接口
//其實location.getAddrStr();就可以拿到地址
if(userLatLng != null){
mGeoCoder.reverseGeoCode(new ReverseGeoCodeOption()
.location(userLatLng));
}
mLocationClient.stop();
}
}
@Override
public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {
if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
Host.showToast(R.string.map_result_error);
return;
}
baiduMap.addOverlay(new MarkerOptions().position(result.getLocation())
.icon(BitmapDescriptorFactory
.fromResource(R.drawable.baidu_map_marka)));
baiduMap.setMapStatus(MapStatusUpdateFactory.newLatLng(result
.getLocation()));
mPosition = result.getAddress().toString();//以上代碼忽略,這裏的mPosition就是具體的地址
PlanNode stNode = null, enNode = null; //聲明兩個節點,stNote 起始節點, enNode目的地節點
if(!IsExchanged) //這裏的if else 可忽略,是爲了實現目標地址與當前地址互換效果而做的
{
myAddress.setText(mPosition);
stNode = PlanNode.withLocation(userLatLng);//將經緯度對象傳入
enNode = PlanNode.withLocation(latLng);
}else
{
targetAddress.setText(mPosition);
enNode = PlanNode.withLocation(userLatLng);
stNode = PlanNode.withLocation(latLng);
}
StartRouteSearch(stNode, enNode); //開始搜索
}
/**
* 發起路線規劃請求,獲取路線
* 回調接口爲onGetTransitRouteResult/onGetWalkingRouteResult/onGetDrivingRouteResult
* @param stNode
* @param enNode
*/
private void StartRouteSearch(PlanNode stNode, PlanNode enNode) {
route = null;
baiduMap.clear(); //每次重新搜索都清空地圖上的所有標記以及路線
if (searchType == SearchType.BUS) {
mSearch.drivingSearch((new DrivingRoutePlanOption()).from(stNode).to(enNode)); //搜索駕車路線
} else if (searchType == SearchType.CAR) {
mSearch.transitSearch((new TransitRoutePlanOption()).from(stNode).city("無錫").to(enNode));//搜索公交路線
} else if (searchType == SearchType.WALK) {
mSearch.walkingSearch((new WalkingRoutePlanOption()).from(stNode).to(enNode));//搜索行走路線
}
}
這裏的三鍾搜索方式對應三個不同的回調接口,分別是:
@Override
public void onGetDrivingRouteResult(DrivingRouteResult dRouteResult) {
if (dRouteResult == null || dRouteResult.error != SearchResult.ERRORNO.NO_ERROR) {
Host.showToast(R.string.map_result_error);
}
if (dRouteResult.error == SearchResult.ERRORNO.AMBIGUOUS_ROURE_ADDR) {
// 起終點或途經點地址有岐義,通過以下接口獲取建議查詢信息
// result.getSuggestAddrInfo()
return;
}
if (dRouteResult.error == SearchResult.ERRORNO.NO_ERROR) {
// nodeIndex = -1;
route = dRouteResult.getRouteLines().get(0); //獲取路線
DrivingRouteOverlay overlay = new DrivingRouteOverlay(baiduMap);
routeOverlay = overlay;
baiduMap.setOnMarkerClickListener(overlay);
overlay.setData(dRouteResult.getRouteLines().get(0));//overLay 爲在地圖上的路徑 ,這裏爲它設置數據
overlay.addToMap(); //添加到地圖
overlay.zoomToSpan();
}
}
@Override
public void onGetWalkingRouteResult(WalkingRouteResult result) {
if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
Host.showToast(R.string.map_result_error);
}
if (result.error == SearchResult.ERRORNO.AMBIGUOUS_ROURE_ADDR) {
// 起終點或途經點地址有岐義,通過以下接口獲取建議查詢信息
// result.getSuggestAddrInfo()
return;
}
if (result.error == SearchResult.ERRORNO.NO_ERROR) { //同上
route = result.getRouteLines().get(0);
WalkingRouteOverlay overlay = new WalkingRouteOverlay(baiduMap);
baiduMap.setOnMarkerClickListener(overlay);
routeOverlay = overlay;
overlay.setData(result.getRouteLines().get(0));
overlay.addToMap();
overlay.zoomToSpan();
}
}
@Override
public void onGetTransitRouteResult(TransitRouteResult result) {
if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
Host.showToast(R.string.map_result_error);
}
if (result.error == SearchResult.ERRORNO.AMBIGUOUS_ROURE_ADDR) {
// 起終點或途經點地址有岐義,通過以下接口獲取建議查詢信息
// result.getSuggestAddrInfo()
return;
}
if (result.error == SearchResult.ERRORNO.NO_ERROR) { //同上
route = result.getRouteLines().get(0);
TransitRouteOverlay overlay = new TransitRouteOverlay(baiduMap);
baiduMap.setOnMarkerClickListener(overlay);
routeOverlay = overlay;
overlay.setData(result.getRouteLines().get(0));
overlay.addToMap();
overlay.zoomToSpan();
}
}
這樣一個基本的百度地圖路徑搜索就完成了.