不知不觉研究百度地图也已经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举个栗子,当然还有更多的我也不会丢下的,可能在以后的学习过程中会补充上去。