1. 程式人生 > >Android studio 百度地圖開發(8)地圖已標記POI點和搜尋POI點的獲取和利用

Android studio 百度地圖開發(8)地圖已標記POI點和搜尋POI點的獲取和利用

一.簡要描述

百度地圖的POI點可以分有兩種:地圖中已經標記的點和通過關鍵詞搜尋得到的POI點。對於這兩種POI點,百度封裝成了不同的類和介面來實現監聽,下面簡單講一點。

二.地圖中已標記POI點

首先遇到的第一個問題就時如何獲取已標記點的資訊,在百度地圖點選已標記的點會有資訊的,那麼在自己的地圖上如何產生點選事件呢?

(1)介面

百度提供了一個POI點選事件的介面 BaiduMap.OnMapClickListener,該介面提供了兩個方法,如下表。
(測試下CSDN的MarkDown編輯器畫表格的功能,不會把首行的標題居中呀)

返回型別 方法 說明
boolean onMapClick(LatLng point) 地圖單擊事件回撥函式
boolean onMapPoiClick(MapPoi poi) 地圖內 Poi 單擊事件回撥函式

(2)MapPoi 類

返回型別 方法 說明
java.lang.String getName() 獲取該興趣點的名稱
LatLng getPosition() 獲取該興趣點的地理座標

(3)獲取POI

我們只需要重寫onMapPoiClick()就可以了。
程式碼如下:

 baiduMap.setOnMapClickListener(new
BaiduMap.OnMapClickListener() { @Override public void onMapClick(LatLng latLng) { } @Override public boolean onMapPoiClick(MapPoi mapPoi) { String POIName = mapPoi.getName();//POI點名稱 LatLng POIPosition = mapPoi.getPosition();//POI點座標
//下面就是自己隨便應用了 //根據POI點座標反向地理編碼 //reverseSearch(POIPosition); //新增圖層顯示POI點 /*baiduMap.clear(); baiduMap.addOverlay( new MarkerOptions() .position(POIPosition) //座標位置 .icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_marka)) .title(POIName) //標題 ); //將該POI點設定為地圖中心 baiduMap.setMapStatus(MapStatusUpdateFactory.newLatLng(POIPosition));*/ return true; } });

其次,為了獲得該POI點的其他詳細資訊,因為MapPoi沒有uid,我嘗試通過對position進行反向地理編碼,結果還是不太滿意,百度地圖上直接點選已標記的POI點,是可以獲得該點的很多資訊的(可見下面的第三部分中PoiInfo),關於這一點,暫時還沒找到更好的方式解決。

三.搜尋關鍵詞獲取POI點

1.描述

該功能就是百度地圖首頁的頂端,輸入想要去的地方或者食物、店鋪等名詞進行POI搜尋,但是這部分分兩種查詢結果:
(1)根據關鍵詞直接搜尋到的相關POI,對應包為com.baidu.mapapi.search.poi;
(2)根據關鍵詞進行聯想得到的POI,對應包為com.baidu.mapapi.search.sug。

所謂聯想搜尋得到的POI,比如我們輸入上海的時候,百度會聯想搜尋將結果提示給你:上海菜、上海大眾汽車等等,如下圖
這裡寫圖片描述
2.兩種POI有用不同的介面、回撥函式、資料型別,如下表:

(1)com.baidu.mapapi.search.poi

介面:OnGetPoiSearchResultListener

型別 方法 說明
void onGetPoiDetailResult(PoiDetailResult result) poi詳情查詢結果回撥
void onGetPoiResult(PoiResult result) poi 查詢結果回撥

然後主要需要了解的是

PoiResult類

這裡寫圖片描述

PoiInfo類

這裡寫圖片描述

搜尋POI

private AutoCompleteTextView keyWorldsView;//輸入搜尋文字的AutoCompleteTextView 
private PoiSearch mPoiSearch;//POI搜尋模組
mPoiSearch = PoiSearch.newInstance();//例項化
PoiSearch.setOnGetPoiSearchResultListener(this);//監聽介面
//*****
//比如在onclick事件裡新增:搜尋->進入回撥函式:onGetPoiResult(PoiResult result)
mPoiSearch.searchInCity((new PoiCitySearchOption())//
              .city(currentLoction.getCity())//定位的城市為搜尋city
              .keyword(keyWorldsView.getText().toString())//關鍵詞
              .pageNum(loadIndex));//第幾頁:預設從0開始,分頁為10,所以如果搜尋結果大於10,要顯示多餘10的部分就需要進行loadIndex=頁碼,或者loadIndex++等來更改loadIndex顯示下一頁資料

接下來就是onGetPoiResult(PoiResult result)

 public void onGetPoiResult(PoiResult result) {
        if (result == null
                || result.error == SearchResult.ERRORNO.RESULT_NOT_FOUND) {
            Toast.makeText(PoiSearchDemo.this, "未找到結果", Toast.LENGTH_LONG)
                    .show();
            return;
        }
        if (result.error == SearchResult.ERRORNO.NO_ERROR) {
            //成功在傳入的搜尋city中搜索到POI
            //對result進行一些應用
            //一般都是新增到地圖中,然後繫結一些點選事件
            //官方Demo的處理如下:
            mBaiduMap.clear();
            PoiOverlay overlay = new MyPoiOverlay(mBaiduMap);
            mBaiduMap.setOnMarkerClickListener(overlay);
            //MyPoiOverlayextends PoiOverlay;PoiOverlay extends OverlayManager
            //看了這三個class之間的關係後瞬間明白咱自己也可以寫overlay,重寫OverlayManager中的一些方法就可以了
            //比如重寫了點選事件,這個方法真的太好,對不同型別的圖層可能有不同的點選事件,百度地圖3.4.0之後就支援設定多個監聽物件了,只是本人還沒把這個方法徹底掌握...
            overlay.setData(result);//圖層資料
            overlay.addToMap();//新增到地圖中(新增的都是marker)
            overlay.zoomToSpan();//保證能顯示所有marker
            return;
        }
        if (result.error == SearchResult.ERRORNO.AMBIGUOUS_KEYWORD) {

            // 當輸入關鍵字在本市沒有找到,但在其他城市找到時,返回包含該關鍵字資訊的城市列表
            String strInfo = "在";
            for (CityInfo cityInfo : result.getSuggestCityList()) {
                strInfo += cityInfo.city;
                strInfo += ",";
            }
            strInfo += "找到結果";
            Toast.makeText(PoiSearchDemo.this, strInfo, Toast.LENGTH_LONG)
                    .show();
        }
    }

(2)com.baidu.mapapi.search.sug

介面

該包就一個void onGetSuggestionResult(SuggestionResult result)

SuggestionResult.seggestionInfo

從欄位說明中可以看到,聯想搜尋的結果都是已經標記的POI點,擁有uid
這裡寫圖片描述

聯想搜尋

 @Override
    public void onGetSuggestionResult(SuggestionResult res) {
        if (res == null || res.getAllSuggestions() == null) {
            return;
        }    
        suggest = new ArrayList<String>();//獲取聯想搜尋結果
        for (SuggestionResult.SuggestionInfo info : res.getAllSuggestions()) {
            if (info.key != null) {
                suggest.add(info.key);
            }
        }
        sugAdapter = new ArrayAdapter<String>(PoiSearchDemo.this, android.R.layout.simple_dropdown_item_1line, suggest);//介面卡,當然可以給加上item的click事件進行處理
        keyWorldsView.setAdapter(sugAdapter);
        keyWorldsView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                SuggestionResult.SuggestionInfo info = res.getAllSuggestions().get(position);
                //String uid = info.uid;
                mPoiSearch.searchPoiDetail((new PoiDetailSearchOption())//去搜索該POI的詳情->onGetPoiDetailResult(PoiDetailResult result)
                        .poiUid(info.uid));
            }
        });
        sugAdapter.notifyDataSetChanged();
    }

四.搜尋效果

(1)聯想搜尋效果

這裡寫圖片描述

(2)直接搜尋效果

搜尋餐廳的結果:其實這裡還可以個性化處理,比如在定位的附近搜尋等等
這裡寫圖片描述

(3)選擇一條聯想搜尋結果

選在一條聯想搜尋結果的顯示:
這裡寫圖片描述

五.總結

就如前面所說,OverlayManager的重寫,可以讓我們對圖層進行一些個性化的處理是非常容易的,只是自己的前期做的時候並沒有發現這一點,而且有對圖層的一些操作,所以現在想重構圖層相關的程式碼真的一時半會還完成不了。