最近做了这个功能,分享一下,用的是百度地图api,和美团外卖的地址选择界面差不多,也就是可以搜索或者滑动地图展示地址列表给用户选择,看下效果图先。

addressSelect.gif

文章重点

1、展示地图并定位到“我”的位置

2、滑动地图获取周边poi(逆地理编码)

3、搜索框输入查询poi(POI检索)

前言

这里先提一下,我们要选择的地址信息其实是POI(Point of Interest),即“兴趣点”。在地理信息系统中,一个POI可以是一栋房子、一个景点、一个邮筒或者一个公交站等。

百度地图SDK提供三种类型的POI检索:城市内检索、周边检索和区域检索(即矩形区域检索)。这里我就不详细介绍了,具体请查看百度地图开发文档(http://lbsyun.baidu.com/index.php?title=androidsdk)。

需求分析

我们要实现的功能主要包括两个操作:滑动地图和搜索框搜索。

滑动地图:滑动地图主要是获取滑动后地图中心点坐标,然后获取poi信息,但是这里不能用上面提到的三种POI检索方式,POI检索都需要传入关键字(不能为空),而我们仅仅只是滑动地图,所以需要用另外一种方式:逆地理编码检索。使用逆地理编码检索时,可以通过检索结果ReverseGeoCodeResult类的getPoiList()方法获取传入位置周围的POI信息。

搜索框搜索:这里就可以使用百度地图SDK提供的三种POI检索方式来进行检索,同时为了方便查看,还可以计算出每个POI和用户之间的距离。

具体实现

一、展示地图并定位到“我”的位置

1.展示地图

展示地图非常简单,首先需要调用SDKInitializer.initialize()方法来进行初始化操作,它接收一个全局的Context参数,记得初始化操作一定要在setContentView()方法前调用(可以到application中进行初始化),然后调用findViewById()方法获取MapView实例,最后记得要对MapView进行资源释放。

2.移动到我的位置

2.1 获取我的位置

首先要确定自己的位置,代码如下所示:

public class MainActivity extends AppCompatActivity implements OnGetPoiSearchResultListener {

private MyLocationListener myListener = new MyLocationListener();

public LocationClient mLocationClient = null;

private LocationClientOption option = null;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

initLocation();

}

/**

* 初始化定位相关

*/

private void initLocation() {

// 声明LocationClient类

mLocationClient = new LocationClient(getApplicationContext());

mLocationClient.setLocOption(option);

// 注册监听函数

mLocationClient.registerLocationListener(myListener);

mLocationClient.start();

}

/**

* 监听当前位置

*/

public class MyLocationListener extends BDAbstractLocationListener {

@Override

public void onReceiveLocation(BDLocation location) {

//mapView 销毁后不在处理新接收的位置

if (location == null || mMapView == null) {

return;

}

if (location.getLocType() == BDLocation.TypeGpsLocation

|| location.getLocType() == BDLocation.TypeNetWorkLocation) {

Log.e(TAG, "当前“我”的位置:" + location.getAddrStr());

navigateTo(location);

}

}

}

}

可以看到,我们首先创建LocationClient实例,然后调用LocationClient的registerLocationListener()方法来注册一个定位监听器,当获取到位置信息的时候,就会回调这个定位监听器。开启定位很简单,只需要调用一下LocationClient的start()方法就可以了。

定位的结果会回调到监听器中,也就是MyLocationListener,在onReceiveLocation()方法中即可通过BDLocation对象获取相关位置详细信息。

注:定位属于危险权限,所以要动态权限申请,记得不要忘记了。

2.2 移动到我的位置

获取到定位后就需要将地图中心点移动到当前位置,代码如下:

private boolean isFirstLocation = true;

/**

* 根据获取到的位置在地图上移动“我”的位置

*

* @param location

*/

private void navigateTo(BDLocation location) {

double longitude = location.getLongitude();

double latitude = location.getLatitude();

if (isFirstLocation) {

currentLatLng = new LatLng(latitude, longitude);

MapStatus.Builder builder = new MapStatus.Builder();

MapStatus mapStatus = builder.target(currentLatLng).zoom(17.0f).build();

mBaiduMap.animateMapStatus(MapStatusUpdateFactory

.newMapStatus(mapStatus));

isFirstLocation = false;

}

//让“我”显示在地图上

MyLocationData.Builder locationBuilder = new MyLocationData.Builder();

locationBuilder.latitude(location.getLatitude());

locationBuilder.longitude(location.getLongitude());

MyLocationData locationData = locationBuilder.build();

mBaiduMap.setMyLocationData(locationData);

}

这里首先将位置信息封装到LatLng对象中,然后调用MapStatusUpdateFactory

的newMapStatus()将LatLng对象传入,接着返回的MapStatusUpdate对象作为参数传入到BaiduMap的animateMapStatus()方法中。上述代码中还使用了一个变量来防止多次调用animateMapStatus()方法,因为移动地图只需要在程序第一次定位时调用一次。

同时为了显示一个当前设备的光标,可以利用MyLocationData.Builder类来实现,如代码所示,就可将“我”显示在地图上了。

二、滑动地图获取poi(逆地理编码)

1. 逆地理编码

前面已经提到了,我们这里滑动地图需要用到逆地理编码,也就是反向地理解析,逆地理编码就是将坐标转换为详细的地址信息,代码如下:

//反向地理解析(含有poi列表)

mGeoCoder.reverseGeoCode(new ReverseGeoCodeOption().location(center));

/**

* 反向地理解析,结果中含有poi信息,用于刚进入地图和移动地图时使用

*/

private void initGeoCoder() {

mGeoCoder = GeoCoder.newInstance();

mGeoCoder.setOnGetGeoCodeResultListener(new OnGetGeoCoderResultListener() {

@Override

public void onGetGeoCodeResult(GeoCodeResult geoCodeResult) {

}

@Override

public void onGetReverseGeoCodeResult(ReverseGeoCodeResult reverseGeoCodeResult) {

if (reverseGeoCodeResult.error.equals(SearchResult.ERRORNO.NO_ERROR)) {

//获取poi列表

if (reverseGeoCodeResult.getPoiList() != null) {

poiInfoListForGeoCoder = reverseGeoCodeResult.getPoiList();

}

} else {

Toast.makeText(mContext, "该位置范围内无信息", Toast.LENGTH_SHORT);

}

}

});

}

这里我们首先获取一个GeoCoder实例,然后注册监听器,当有解析结果时便会回调到onGetReverseGeoCodeResult()方法中,而解析结果便有我们需要的poi列表。反向解析只需要调用GeoCoder的reverseGeoCode()方法并传入移动后地图的中心坐标点即可。

2. 监听地图滑动

百度地图提供了一个地图状态改变的监听器,当双击、滑动、缩放等操作时便进行回调,如下:

mBaiduMap.setOnMapStatusChangeListener(new BaiduMap.OnMapStatusChangeListener() {

/**

* 手势操作地图,设置地图状态等操作导致地图状态开始改变。

* @param mapStatus 地图状态改变开始时的地图状态

*/

@Override

public void onMapStatusChangeStart(MapStatus mapStatus) {

}

/** 因某种操作导致地图状态开始改变。

* @param mapStatus 地图状态改变开始时的地图状态

* @param i 取值有:

* 1:用户手势触发导致的地图状态改变,比如双击、拖拽、滑动底图

* 2:SDK导致的地图状态改变, 比如点击缩放控件、指南针图标

* 3:开发者调用,导致的地图状态改变

*/

@Override

public void onMapStatusChangeStart(MapStatus mapStatus, int i) {

Log.e(TAG, "地图状态改变开始时:" + i + "");

}

/**

* 地图状态变化中

* @param mapStatus 当前地图状态

*/

@Override

public void onMapStatusChange(MapStatus mapStatus) {

LatLng latlng = mBaiduMap.getMapStatus().target;

addMarker(latlng);

}

/**

* 地图状态改变结束

* @param mapStatus 地图状态改变结束后的地图状态

*/

@Override

public void onMapStatusChangeFinish(MapStatus mapStatus) {

center = mBaiduMap.getMapStatus().target;

//反向地理解析(含有poi列表)

mGeoCoder.reverseGeoCode(new ReverseGeoCodeOption()

.location(center));

}

});

如上,当地图从滑动到结束会回调4个方法,我们需要用到的是:地图状态变化中和地图状态改变结束,也就是对应地图滑动中和滑动结束时。

滑动结束:当滑动结束时便调用反向地理解析出结果,这个上面已经说了。

滑动中:我们会发现当我们滑动地图时,地图上会有一个图标始终处于地图中心,这里就是利用地图状态变化中这个回调来添加一个marker,也就是在地图上添加一个图标,不过这个方法一次滑动可能会回调很多次,但是如果只在滑动结束后添加,用户体验不好,所以如果实在要考虑性能的话可以换个思路,将图标固定在屏幕上大致地图的中心,这样滑动地图看起来也一样的。

添加marker的方法就不详解了,源码里有,一看就懂了。

三、搜索框输入查询poi(POI检索)

搜索框搜索也就是使用关键字检索POI信息,这里不要和Sug检索弄混了,Sug(Suggestion POI search)检索是根据部分关键字检索出可能的完整关键字名称,即关键字匹配。而POI检索是根据关键字检索符合的POI具体信息。

上面说过POI检索有三种方式,这里结合我们的需求来说,使用城市内检索更加合适,也就是传入城市和关键字进行查询,当然你也可以使用另外两种检索方式,步骤如下:

1. 创建POI检索实例

mPoiSearch = PoiSearch.newInstance();

2. 创建POI检索监听器

OnGetPoiSearchResultListener listener = new OnGetPoiSearchResultListener() {

/**

* 获取POI搜索结果

* @param poiResult Poi检索结果,包括城市检索,周边检索,区域检索

*/

@Override

public void onGetPoiResult(PoiResult poiResult) {

if (poiResult.error == SearchResult.ERRORNO.NO_ERROR) {

poiInfoListForSearch = poiResult.getAllPoi();//POI集合

}

if (poiResult.error == SearchResult.ERRORNO.AMBIGUOUS_KEYWORD) {

// 当输入关键字在本市没有找到,但在其他城市找到时,返回包含该关键字信息的城市列表

String strInfo = "在";

for (CityInfo cityInfo : poiResult.getSuggestCityList()) {

strInfo += cityInfo.city;

strInfo += ",";

}

strInfo += "找到结果";

Toast.makeText(mContext, strInfo, Toast.LENGTH_LONG).show();

}

}

@Override

public void onGetPoiDetailResult(PoiDetailSearchResult poiDetailSearchResult) {

}

@Override

public void onGetPoiIndoorResult(PoiIndoorResult poiIndoorResult) {

}

//废弃

@Override

public void onGetPoiDetailResult(PoiDetailResult poiDetailResult) {

}

};

3. 设置检索监听器

mPoiSearch.setOnGetPoiSearchResultListener(listener);

4. 发起检索请求

mPoiSearch.searchInCity((new PoiCitySearchOption())

.city(cityName)//城市名称

.keyword(keyword)//必填

.pageCapacity(pageSize)//每页条数

.pageNum(loadIndex));//分页页码

5. 释放检索实例

mPoiSearch.destroy();

为了方便用户查看,我们可以在列表中展示每一个poi和用户之间的距离,利用DistanceUtil类的getDistance()方法传入两个点坐标的LatLng对象即可计算,如下:

double distance=DistanceUtil.getDistance(currentLatLng, latLng);

最后利用EditText的addTextChangedListener监听器监听输入框,如果值改变就进行检索。

至此,整个功能也就做完了,demo里没有做列表分页和动态权限申请,这个常用的你们就自个加咯,最后放下demo地址:

GitHub:https://github.com/yangxch/BaiDuMapSelectDemo

如果觉得有帮助,帮忙点个赞吧!

android 仿美团骑手地图_Android仿美团地址选择相关推荐

  1. android 仿美团骑手地图_Android仿美团外卖菜单界面

    美团外卖菜单界面的Android实现代码,供大家参考,具体内容如下 布局文件 总布局 xmlns:tools="http://schemas.android.com/tools" ...

  2. android 微信浮窗实现_Android仿微信视屏悬浮窗效果

    在项目中需要对接入的腾讯云音视频,可以悬浮窗显示,悬浮窗可拖拽,并且在悬浮窗不影响其他的activity的焦点. 这个大神的文章Android基于腾讯云实时音视频仿微信视频通话最小化悬浮,他讲的是视频 ...

  3. android 仿微信选取相册_Android 仿微信 相册多图选择器

    下载方式 com.sh.zsh.code shphotoselectorlibrary 2.0.9 pom or Gradle: compile 'com.sh.zsh.code:shphotosel ...

  4. android 微信缩小通话界面_Android仿微信多人音视频通话界面

    工作中需要实现一个类似微信多人视频通话功能的界面,分别使用自定义viewgroup和自定义layoutmanager的方式进行了实现.最终工作中采用了layoutmanager,因为可以使用paylo ...

  5. android 仿京东地址选择_Android 开发:仿美团地址选择

    最近做了这个功能,分享一下,用的是百度地图api,和美团外卖的地址选择界面差不多,也就是可以搜索或者滑动地图展示地址列表给用户选择,看下效果图先. 文章重点 展示地图并定位到"我" ...

  6. android仿美团外卖选择地址,Android仿美团地址选择

    最近做了这个功能,分享一下,用的是百度地图api,和美团外卖的地址选择界面差不多,也就是可以搜索或者滑动地图展示地址列表给用户选择,看下效果图先. addressSelect.gif 文章重点 1.展 ...

  7. android 辐射动画_Android仿微信雷达辐射搜索好友(逻辑清晰实现简单)

    不知不觉这个春节也已经过完了,遗憾家里没网,没能及时给大家送上祝福,今天回到深圳,明天就要上班了,小伙伴们是不是和我一样呢?今天讲的是一个大家都见过的动画,雷达搜索好友嘛,原理也十分的简单,你看完我的 ...

  8. 外卖也智能!美团骑手智能助手的技术与实践

    点击关注 InfoQ,置顶公众号 接收程序员的 8 点技术早餐 作者 | 何仁清 编辑 | 臧秀涛 随着数字化时代的到来,外卖市场近年来发展非常迅猛.对外卖物流系统而言,配送效率和用户体验至关重要.而 ...

  9. Android 使用ViewPager2+ExoPlayer+VideoCache 实现仿抖音视频翻页播放

    1. 实现效果 效果图中,视频没有铺满 是因为使用了ExoPlayer的RESIZE_MODE_FIT模式, 虽然使用RESIZE_MODE_FILL模式可以填充整个父布局,但是本Demo中使用的视频 ...

最新文章

  1. 自建ELK vs 日志服务(SLS)全方位对比
  2. mysql复习增删改查
  3. rm命令改为移动到回收站
  4. 处理数据不均衡的策略
  5. Linux 命令(108)—— ifconfig 命令
  6. SUSE Labs Con 2018有感
  7. 人工智能python3+tensorflow人脸识别_Tensorflow+opencv2实现人脸识别
  8. python和pycharm版本要对应吗_pycharm的版本问题
  9. java程序员 英文简历_it程序员英文简历范文模板
  10. 【142】阿蛮歌霸使用技巧
  11. easyUI——easyUI(入门)
  12. VINS-Mono 代码解析——视觉跟踪 feature_trackers
  13. 动作游戏的打击感和音效的关系
  14. 为BlueLake主题增加自定义icon图标
  15. 如何用计算机处理信息,计算机信息处理
  16. 关于 MySQLTransactionRollbackException 异常的排查经历
  17. 最新版Paypal取消到期自动续费(循环付款)教程
  18. CRS-4000启动crs报错问题处理
  19. 锐捷(一)清除三层交换机配置
  20. 三个故事,说穿了许多人

热门文章

  1. python后端学习(十四)元类、ORM
  2. 转: 关于UI开发(总结一些技术和一些论坛牛人讨论)
  3. Flash Memory存储器
  4. 关于Unity3d中的自动寻路
  5. UnblockNeteaseMusic手机端使用教程
  6. 如何在Mac上设置iMessage?
  7. Frida 基础环境部署和运行第一个 hook demo
  8. 深入浅出:全面解析服务器基础知识
  9. 运维基础知识硬件总结
  10. 【商城应用】类余额宝功能体系设计