Android百度地圖開發POI(三)
我們經常需要在地圖上顯示一些特別的東西,比如一些服務如銀行,KFG,學校等等,這樣就需要使用POI搜尋,基本上的步驟如下
0.所需要的變數
//POI搜尋
private MyPoiOverlay mTrafficOverLay;// 交通圖層
private MyPoiOverlay mSchoolOverLay;// 學校圖層
private MyPoiOverlay mLiveOverLay;// 生活圖層
private PoiSearch mPoiSearch;//搜尋服務
private float latitude = 31.1803029f;
private float longitude = 121.4864084f;
圖層可以定義N多,只要你能夠放下就OK!
1.地圖初始化工作
在非同步執行緒中初始化好百度地圖,initBaiduMap();
2.定義自己的圖層.
/**
* 使用者poi自定義圖
*/
class MyPoiOverlay extends PoiOverlay {
public MyPoiOverlay(com.baidu.mapapi.map.BaiduMap arg0) {
super(arg0);
}
/**
*覆蓋物的點選事件
*/
@Override
public boolean onPoiClick(int arg0) {
super.onPoiClick(arg0);
PoiInfo poiInfo = getPoiResult().getAllPoi().get(arg0);
// 檢索poi詳細資訊
mPoiSearch.searchPoiDetail(new PoiDetailSearchOption()
.poiUid(poiInfo.uid));
return true;
}
}
3.初始化自定義圖層;
mTrafficOverLay = new MyPoiOverlay(mBaiduMap);
mSchoolOverLay = new MyPoiOverlay(mBaiduMap);
mLiveOverLay = new MyPoiOverlay(mBaiduMap);
這些初始化工作還是放在initBaiduMap()方法中進行.
4.設定搜尋方式
搜尋方式有一下三種,根據不同的需求來做,這這三個方法都有一個傳入引數,page,當我們發起POI搜尋時會搜到很多條,而這些搜尋結果可以分為N頁,每頁N條這個page是顯示第幾頁.也可以不用這個引數去掉pageNum(page)這段程式碼,在圖層新增方法中加入mLiveOverLay.zoomToSpan();方法將所有的結果都顯示出來.
/**
* 城市內搜尋
*/
private void citySearch(int page) {
// 設定檢索引數
PoiCitySearchOption citySearchOption = new PoiCitySearchOption();
citySearchOption.city("上海");// 城市
citySearchOption.keyword("KFC");// 關鍵字
citySearchOption.pageCapacity(15);// 預設每頁10條
citySearchOption.pageNum(page);// 分頁編號
// 發起檢索請求
mPoiSearch.searchInCity(citySearchOption);
}
/**
* 範圍檢索
*/
private void aroundSearch(int page) {
PoiBoundSearchOption boundSearchOption = new PoiBoundSearchOption();
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();// 得到一個地理範圍物件
boundSearchOption.bound(bounds);// 設定poi檢索範圍
boundSearchOption.keyword("美食");// 檢索關鍵字
boundSearchOption.pageNum(page);
mPoiSearch.searchInBound(boundSearchOption);// 發起poi範圍檢索請求
}
/**
* 附近檢索
*/
private void nearSearch(int page) {
PoiNearbySearchOption nearbySearchOption = new PoiNearbySearchOption();
nearbySearchOption.location(new LatLng(latitude, longitude));
nearbySearchOption.keyword("學校");
nearbySearchOption.radius(1000);// 檢索半徑,單位是米
//nearbySearchOption.pageNum(page);
mPoiSearch.searchNearby(nearbySearchOption);// 發起附近檢索請求
}
5.圖層新增.
我們可以在介面中定義幾個Button,比如學校,生活,KFG,銀行,交通等,按一個按鍵顯示一種POI搜尋結果,多種圖層可以同時顯示.這個過程就不寫出了,都會寫的!我們統一寫一個在Map中新增圖層的方法addOverLay(MyOverLay overLay),放在UI執行緒中
@UiThread(propagation = UiThread.Propagation.REUSE)
void addMyOverLay(PoiResult poiResult) {
mLiveOverLay.setData(poiResult);
mLiveOverLay.addToMap();
// 縮放地圖,使所有Overlay都顯示
mLiveOverLay.zoomToSpan();
mBaiduMap.setOnMarkerClickListener(mLiveOverLay);//設定覆蓋物的點選事件
}
6.設定POI監聽事件
如果搜尋成功那將結果新增到圖層,如果搜尋失敗進行提示.
/**
* POI檢索監聽器
*/
OnGetPoiSearchResultListener poiSearchListener = new OnGetPoiSearchResultListener() {
/**
* 搜尋完畢後的回撥事件,當搜素完畢後可以給與使用者提示!
*/
@Override
public void onGetPoiResult(PoiResult poiResult) {
if (poiResult.error == SearchResult.ERRORNO.NO_ERROR) {//搜尋正常
addMyOverLay(poiResult);//新增圖層
} else {
Toast.makeText(BaiduMap.this, "chu cuo" + poiResult.error , Toast.LENGTH_LONG).show();
}
}
/**
* 點選一個覆蓋物後回撥的事件,比如如果點選一個覆蓋物後沒有該覆蓋物的詳細資訊,在這裡可以提示並得到失敗的原因
*/
@Override
public void onGetPoiDetailResult(PoiDetailResult poiDetailResult) {
}
};
7.初始化,搜尋服務類.
這個類百度的3.0之前和之後有所不同.這個方法也在initBaiduMap()方法中呼叫
/**
* 初始化POI搜尋
*/
private void checkSearchParam() {
if (null == mPoiSearch) {
mPoiSearch = PoiSearch.newInstance();
mPoiSearch.setOnGetPoiSearchResultListener(poiSearchListener);
}
}
8.圖層的顯示.
當我們按下按鍵顯示一種POI搜尋結果.
public void onClick(View v) {
switch (v.getId()) {
case R.id.map_detail_back_tv:// 返回
this.finish();
break;
case R.id.map_live://生活
isLiveSelect = !isLiveSelect;
nearbySearch(1);
break;
.....
}
}
9.清除POI
@Click(R.id.button_clean)
void poiClean() {
mLiveOverLay.removeFromMap();
}
擴充套件
這樣基本上POI搜尋就完畢了.不過有種需求比如我們搜尋了學校,和KFG兩種同時顯示,但是百度地圖3.0以上的版本搜尋結果都是紅色汽包這樣很難分清楚,而且官方似乎也沒有相應的方法提供給我們.這樣需要我們自己想辦法.我找到了兩種方法.
第一種 :程式碼很簡單,但是弊端是沒有了POI點選事件的產生了,
我們將新增圖層方法改成如下:
@UiThread(propagation = UiThread.Propagation.REUSE)
void addMyOverLay(PoiResult poiResult) {
mLiveOverLay.setData(poiResult);
//mLiveOverLay.addToMap();//如果不註釋掉圖層上會顯示兩種氣泡重合
List<OverlayOptions> ops = new ArrayList<OverlayOptions>();
List<PoiInfo> pois = poiResult.getAllPoi();
BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(R.mipmap.ic_location);
for(int i = 0;i < pois.size();i++){
OverlayOptions op = new MarkerOptions().position(pois.get(i).location).icon(bitmap);
ops.add(op);
mBaiduMap.addOverlay(op);
}
// 縮放地圖,使所有Overlay都在合適的視野內
mLiveOverLay.zoomToSpan();
mBaiduMap.setOnMarkerClickListener(mLiveOverLay);//加上也沒有用
}
第二種 :我們寫一個繼承OverlayManager的內部類,這個是我在網上找到的一種解決方法,將(private MyPoiOverlay mLiveOverLay;// 生活圖層)改為(private MyOverlayManager mLiveOverLay;// 生活圖層),下面的初始化相應的改變.去掉數子顯示都可以自己進行客製化修改.
/**
* 覆蓋物
*/
class MyOverlayManager extends OverlayManager {
private PoiResult poiResult = null;
public MyOverlayManager(BaiduMap baiduMap) {
super(baiduMap);
}
public void setData(PoiResult poiResult) {
this.poiResult = poiResult;
}
@Override
public boolean onMarkerClick(Marker marker) {
if (marker.getExtraInfo() != null) {
int index = marker.getExtraInfo().getInt("index");
PoiInfo poi = poiResult.getAllPoi().get(index);
// 詳情搜尋
mPoiSearch.searchPoiDetail((new PoiDetailSearchOption())
.poiUid(poi.uid));
return true;
}
return false;
}
@Override
public List<OverlayOptions> getOverlayOptions() {
if ((this.poiResult == null)
|| (this.poiResult.getAllPoi() == null))
return null;
ArrayList<OverlayOptions> arrayList = new ArrayList<OverlayOptions>();
for (int i = 1; i < this.poiResult.getAllPoi().size(); i++) {
if (this.poiResult.getAllPoi().get(i).location == null)
continue;
// 給marker加上標籤
Bundle bundle = new Bundle();
bundle.putInt("index", i);
arrayList.add(new MarkerOptions()
.icon(BitmapDescriptorFactory
.extraInfo(bundle)
.position(this.poiResult.getAllPoi().get(i).location));
}
return arrayList;
}
/**
* 往圖片新增數字
*/
private Bitmap setNumToIcon(int num) {
BitmapDrawable bd = (BitmapDrawable) getResources().getDrawable(R.mipmap.ic_location);
Bitmap bitmap = bd.getBitmap().copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);
int widthX;
int heightY = 0;
if (num < 10) {
paint.setTextSize(30);
widthX = 8;
heightY = 6;
} else {
paint.setTextSize(20);
widthX = 11;
}
canvas.drawText(String.valueOf(num),
((bitmap.getWidth() / 2) - widthX),
((bitmap.getHeight() / 2) + heightY), paint);
return bitmap;
}
@Override
public boolean onPolylineClick(Polyline polyline) {
return false;
}
}
在開發過程中我出現過報錯—>PERMISSION_UNFINISHED,查明原因是因為地圖初始化沒有完成我就去POI搜尋了,我們可以將其放在一個點選事件中或者在程式執行延遲幾秒再去搜索.
POI開發就完畢了,希望大家能多多指點,有不對或者侵權之處請告知謝謝!