不知不覺研究百度地圖也已經3,4天了,雖然我們一直停留在MainActivty上,但是也已經取得很不錯的成果了(有些圖標,UI細節沒有在簡書文章上指出)
可以看到我們的演示效果,雖然畫質渣渣(壓縮gif的緣故)但是也是有點樣子的對吧。
這也算我們實現的第一個階段吧,下一個階段會實現其他的功能,但是可能更新頻率不會很快,我要修養一段時間(開玩笑啦,其實是轉Php去了,不能落下任何一個不是嘛。)不過這個我是不會放棄的,我會堅持把他做到我期待的樣子,并把我開發的全過程用簡書記錄下來。
1.開始今天的旅行
目前百度地圖SDK所集成的檢索服務包括:POI檢索、公交信息查詢、線路規劃、地理編碼、行政區邊界數據檢索、在線建議查詢、短串分享(包括POI搜索結果分享、駕車/公交/騎行/步行路線規劃分享、反向地理編碼結果分享)
POI(Point of Interest)
中文可以翻譯為“興趣點”。在地理信息系統中,一個POI可以是一棟房子、一個商鋪、一個郵筒、一個公交站等。
首先我們看一下我們百度提供的說明,
http://lbsyun.baidu.com/index.php?title=androidsdk/guide/retrieval
這里的檢索主要分為五個步驟,主要有3個類型
下面是百度demo里的一段代碼,主要是顯示在線搜索結果,那么這都是什么意思呢,這里我詳細說一下。
大家可以拿著百度地圖對照,首先我們點擊首頁的搜索框進入一個單獨的頁面,輸入搜索詞,比如說北京大學,這時候下面立馬顯示一排搜索結果,并顯示一些信息,那么本應該就是我們的SuggestionSearch,中文可以譯作搜索建議,這個建議包含了很多數據,包括名稱,地理位置等
但是百度這里用的是onGetPoiResult,(可以看到他每一條都帶有詳細的介紹)我們也打算用這個,
那么我們點擊搜索按鈕的話
可以看到,這里有一個列表,一個地圖,地圖上還有標注。
這里就是我們的onGetPoiResult獲取的結果。
最后還有一個onGetPoiDetailResult,從名字看當然是詳情啦。
梳理結束之后,我們要思考設計一個頁面。
……一個非專業的UI正在苦癟界面……請稍后……
兩天之后……
我終于回來了,那么我回來帶來了什么呢?
個人認為這個界面還是看的過去的,因為畢竟不是專業的UI,所以有些細節還得推敲一下。
當然如果今天我在這里將UI設計的代碼那可能就跑偏了,我最多只會說說這個UI界面是怎么實現的。
首先我們回到首頁
2.UI分析
點擊首頁的toolbar進入搜索頁面,這里的搜索頁面可以看到分為三部分,上方的toolbar,中間的tablayout,下面的viewpager,viewpager中在推薦這個頁面是一個fragment,包含一個列表和一個下拉刷新,后期會添加一些歷史紀錄啥的。
那么我們輸入關鍵字 “天安門廣場” 是怎么出來這個列表的呢?
下面直接上代碼
//這是poi搜索的準備,進行一個初始化,在onCreate()里開始調用
// 初始化搜索模塊,注冊搜索事件監聽
mPoiSearch = PoiSearch.newInstance();
mPoiSearch.setOnGetPoiSearchResultListener(this);
然后他會要求activity實現他的接口里的方法,一共3個
/**
* 獲取POI搜索結果,包括searchInCity,searchNearby,searchInBound返回的搜索結果
* @param result
*/
public void onGetPoiResult(PoiResult result) {
}
/**
* 獲取POI詳情搜索結果,得到searchPoiDetail返回的搜索結果
* @param result
*/
public void onGetPoiDetailResult(PoiDetailResult result) {
}
//暫時先不管這個
@Override
public void onGetPoiIndoorResult(PoiIndoorResult poiIndoorResult) {
}
最后別忘記銷毀釋放資源
@Override
protected void onDestroy() {
//銷毀,釋放資源
mPoiSearch.destroy();
super.onDestroy();
}
這樣我們的一個搜索框架就搭建好了,有建立,監聽和銷毀
下面我們來填充一下。
下面是我們的搜索框的TextWatcher
mpoi_se.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
//先清空列表,這個列表是儲存著onGetPoiResult結果
//的列表,也就是說我們一旦改變了輸入框內容,那么
//以前的數據也就沒用了,必須清空
poi_list.clear();
//這里的判斷也就是說如果獲取到的內容不為空就開始
//搜索,為空就直接調用更新UI的方法更新一個空列表。
if(!mpoi_se.getText().toString().equals("")){
//s_page角色是搜索頁碼,因為搜索結果很多,
//肯定是分頁加載,默認是加載第0頁
s_page = 0;
//這里主要控制著,搜附近還是搜城市
//假如說我們從主頁面進入搜索頁,那就是搜城市
//從搜城市搜出來的結果item項進入它的附近就是搜
//附近,那其實這兩個方法都大同小異,一會在下面貼
if(getIntent().getStringExtra("KEY")!=null){
search_nearby(0);
Log.d("SESO", "GetMessage key: 附近");
}else{
search(0);
Log.d("SESO", "GetMessage key: 城市");
}
//這里我寫了一個通知開始刷新的方法,主要是
//UI上的,如果要寫這個poi搜素,UI可以自己寫
//我就不貼UI相關的代碼了
sendRefreshNotify("START");
}else{
//如果查詢空串自動復位,這就是更新UI的方法
//同樣不貼了
LoadSuggestFragment();
}
}
@Override
public void afterTextChanged(Editable editable) {
}
});
可以看到我們的邏輯還是相當簡單的
1.清空上次搜索的舊數據
2.搜索頁面s_page置為0
3.根據從某個頁面來的intent攜帶的值來判斷是搜城市還是搜附近
那么搜城市的代碼是這樣的
private void search(int i) {
try {
//1.city方法當然填入你現在所在的城市,從主頁面可以獲取到,通
//過Intent傳過來就好
//2.keyword是你的搜索關鍵字也就是輸入框里打的內容
//3.isReturnAddr返回地址為真
//4.pagenum是請求第幾頁啦
mPoiSearch.searchInCity((new PoiCitySearchOption())
.city(getIntent().getStringExtra("CITY")).keyword(mpoi_se.getText().toString())
.isReturnAddr(true)
.pageNum(i));
} catch (Exception e) {
e.printStackTrace();
}
Log.d("SE", "onClick: 開始搜索");
}
搜附近也類似
private void search_nearby(int i) {
Double lati_ = getIntent().getDoubleExtra("LOCATION_latitude",39.92235);
Double long_ = getIntent().getDoubleExtra("LOCATION_longitude",116.380338);
//搜索附近
//keyword不啰嗦
//sortType是一個排序規則,從我們傳遞的參數來看,這個一
//個由近到遠的排序規則
//location是一個坐標點,也就是從誰附近搜這個location就是誰
//radius是一個搜索半徑,單位是m
//pagenum不啰嗦
LatLng latLng = new LatLng(lati_,long_);
PoiNearbySearchOption nearbySearchOption = new PoiNearbySearchOption().keyword(mpoi_se.getText()
.toString()).sortType(PoiSortType.distance_from_near_to_far).location(latLng)
.radius(10000).pageNum(i);
mPoiSearch.searchNearby(nearbySearchOption);
}
這是兩種搜索方法,搜區域我就不說了,如果有人需要的話可以參考百度demo
那么我們的搜索結果在三個重寫的方法里接受,這里主要是第一個方法,其余的都沒有用到
public void onGetPoiResult(PoiResult result) {
//得到結果后,通知停止刷新
sendRefreshNotify("STOP");
//搜索結果,為空或者空錯誤
if (result == null || result.error == SearchResult.ERRORNO.RESULT_NOT_FOUND) {
Toast.makeText(SeActivity.this, "未找到結果", Toast.LENGTH_LONG)
.show();
return;
}
if (result.error == SearchResult.ERRORNO.NO_ERROR) {
//用一個foreach語句將結果傳遞給我們的列表
for (PoiInfo poiInfo : result.getAllPoi()) {
poi_list.add(0,poiInfo);
}
//有了數據,當然是通知ui,加載列表
LoadSuggestFragment();
}
}
那么其實我們的PoiInfo已經包含了這個地方的名字,地址,電話,位置坐標等等,如果你想計算他到某個點的位置還可以通過下面的語法來計算
dis = DistanceUtil.getDistance(latLng, poiInfo.location);
其實一個簡單的poi搜索就這么點東西,初始化,搜索,接收數據,銷毀。
那可能有朋友就會問了,我們重寫的三個方法,只用了一個方法,另外兩個呢?
其實第二個onGetPoiDetailResult是獲取詳情結果,第三個是onGetPoiIndoorResult是獲取室內的結果(我們這里沒考慮室內的情況),我們來看看第二種情況。
首先還是我們的初始化,銷毀,重寫的方法還是那些,只不過我們的搜索變成了這個樣子,這里的poiUid接受一個uid參數,這個參數是onGetPoiResult獲取的結果里的PoiInfo的一個屬性,也就是說我們只要得到onGetPoiResult結果才能使用onGetPoiDetailResult
//查看詳情
mPoiSearch.searchPoiDetail((new PoiDetailSearchOption())
.poiUid(getIntent().getStringExtra("UID")));
那么我們來看一下搜索結果
這里我們直接將搜索結果的detailUrl屬性傳出去了,其實這里還有很多屬性,包括店鋪評價啥的,這里我們就不一一展示了。
@Override
public void onGetPoiDetailResult(PoiDetailResult result) {
if (result.error != SearchResult.ERRORNO.NO_ERROR) {
Toast.makeText(PoiInfoActivity.this, "抱歉,未找到詳情結果", Toast.LENGTH_SHORT)
.show();
} else {
startActivity(new Intent(PoiInfoActivity.this,PoiDetailActivity.class).putExtra("URL",result.detailUrl));
}
}
那么poi檢索到這里也就算結束了
總結
百度地圖檢索功能包含的內容還是很多的,這里我只拿poi舉個栗子,當然還有更多的我也不會丟下的,可能在以后的學習過程中會補充上去。