<menu id="meoaa"><u id="meoaa"></u></menu>
<input id="meoaa"></input>
  • <menu id="meoaa"><u id="meoaa"></u></menu><menu id="meoaa"></menu>
    <input id="meoaa"><u id="meoaa"></u></input>
  • <object id="meoaa"></object>
    <nav id="meoaa"></nav>
  • <menu id="meoaa"></menu>
    <menu id="meoaa"><small id="meoaa"></small></menu><input id="meoaa"><tt id="meoaa"></tt></input>
  • <input id="meoaa"></input>
  • Android仿美团地址选择

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

     

              分享图片

     

    文章重点

    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

     

    原创不易,转载请注明出处!

    相关文章
    相关标签/搜索
    每日一句
      每一个你不满意的现在,都有一个你没有努力的曾经。
    公众号推荐
       一个历史类的公众号,欢迎关注
    一两拨千金
    香港最快現场开奖结果2019年马会全年资料天下彩天空彩票与你同行香港旧版免费资料大全网 文化| 吉木萨尔县| 滁州市| 日土县| 北安市| 明光市| 潢川县| 荆州市| 调兵山市| 志丹县| 项城市| 丰镇市| 沙坪坝区| 揭西县| 桐庐县| 莱芜市| 弥渡县| 甘孜| 桂阳县| 保山市| 万源市| 临澧县| 安化县| 开原市| 沧州市| 连州市| 乌兰浩特市| 介休市| 石首市| 谢通门县| 红安县| 奉节县| 新泰市| 富顺县| 辉县市| 阳泉市| 呼和浩特市| 永胜县| 扎兰屯市| 湖州市| 布拖县| 门头沟区| 阳泉市| 突泉县| 怀来县| 内丘县| 城固县| 资讯| 海口市| 璧山县| 沛县| 宁化县| 孟村| 淮南市| 曲麻莱县| 台北市| 于都县| 民权县| 马尔康县| 耒阳市| 桃园市| 道真| 德惠市| 西乌珠穆沁旗| 安康市| 临泉县| 天峻县| 乐业县| 四平市| 邹平县| 汉中市| 石家庄市| 昭平县| 庄浪县| 稻城县| 石阡县| 景德镇市| 秦皇岛市| 威海市| 锡林浩特市| 应用必备| 绥芬河市| 饶河县| 巴彦淖尔市| 阜南县| 京山县| 白银市| 赤峰市| 宁夏| 尤溪县| 奉化市| 高邮市| 珲春市| 如皋市| 水富县| 丽水市| 邯郸县| 望江县| 黎城县| 南通市| 兴宁市| 桃园县| 合肥市| 达孜县| 南溪县| 武夷山市| 体育| 灵石县| 桂东县| 土默特右旗| 武邑县| 星子县| 深州市| 巫山县| 渝中区| 武威市| 多伦县| 高碑店市| 台南县| 麻江县| 乐陵市| 四平市| 和政县| 崇州市| 赞皇县| 建德市| 连江县| 武陟县| 三台县| 新河县| 如皋市| 当涂县| 修水县| 蚌埠市| 松江区| 泸定县| 太谷县| 嘉禾县| 乌恰县| 延津县| 明星| 满城县| 文成县| 赤壁市| 龙陵县| 扶绥县| 东方市| 临夏市| 鲁甸县| 郓城县| 普兰店市| 渝中区| 滦南县| 资兴市| 临西县| 嘉祥县| 洪雅县| 宿迁市| 芦溪县| 舞阳县| 安阳市| 齐河县| 时尚| 永顺县| 桓台县| 曲沃县| 鸡泽县| 海原县| 锡林浩特市| 楚雄市| 台南市| 南京市| 禹城市| 南阳市| 五华县| 三门峡市| 榆社县| 兴安盟| 蒲江县| 大庆市| 渭源县| 大石桥市| 开阳县| 石狮市| 尼勒克县| 砀山县| 保靖县| 湄潭县| 洱源县| 五峰| 白玉县| 象山县| 江门市| 凤阳县| 乌兰县| 仁寿县| 烟台市| 西昌市| 彰武县| 连州市| 聂拉木县| 历史| 霸州市| 新蔡县| 策勒县| 许昌市| 信宜市| 长乐市| 鸡东县| 海宁市| 邢台市| 康保县| 紫金县| 五常市| 那坡县| 渝中区| 抚宁县| 左云县| 望奎县| 宁陵县| 德江县| 襄城县| 连云港市| 金湖县| 临潭县| 晋宁县| 左权县| 秦安县| 永新县| 柯坪县| 卢氏县| 城固县| 文化| 淅川县| 维西| 时尚| 屏东县| 紫云| 和静县| 雷波县| 安阳市| 普陀区| 遵化市| 陇西县| 方正县| 正宁县| 宝山区| 昭觉县| 南宫市| 克山县| 虹口区| 海门市| 桓仁| 昆明市| 安化县| 满洲里市| 关岭| 株洲县| 花莲县| 桐城市| 津市市| 象州县| 新竹市| 静安区| 綦江县| 襄樊市| 株洲市| 安陆市| 新安县| 隆尧县| 吉林市| 合作市| 灌阳县| 忻州市| 汝南县| 岗巴县| 浦江县| 安丘市| 固原市| 镇原县| 轮台县| 阿拉善盟| 巧家县| 新邵县| 勃利县| 沁水县| 龙州县| 陈巴尔虎旗| 娱乐| 雅江县| 抚顺县| 南丹县| 罗平县| 和政县| 三原县| 温泉县| 大同市| 巴林右旗| 和静县| 石阡县| 滨州市| 梅河口市| 六枝特区| 平遥县| 东阳市| 香港| 南平市| 洛浦县| 信阳市| 辛集市| 襄垣县| 江都市| 长泰县| 菏泽市| 黄冈市| 沁阳市| 饶河县| 青河县| 临安市| 双流县| 广饶县| 双柏县| 杨浦区| 大渡口区| 淳化县| 长岭县| 平远县| 阳西县| 湘潭市| 百色市| 南陵县| 北票市| 思南县| 阳江市| 鄂托克前旗| 大港区| 乳山市| 礼泉县| 霍林郭勒市| 金沙县| 定结县| 南宫市| 邢台县| 二连浩特市| 胶南市| 襄汾县| 尉犁县| 潜山县| 若尔盖县| 克东县| 高陵县| 施甸县| 麟游县| 昔阳县| 崇左市| 满洲里市| 青阳县| 丹棱县| 噶尔县| 吉木萨尔县| 龙山县| 泸定县| 武汉市| 扎兰屯市| 田东县| 霍州市| 阿克苏市| 驻马店市| 普兰县| 唐山市| 永新县| 绥阳县| 酒泉市| 五常市| 根河市| 莫力| 博白县| 麻城市| 杭州市| 绍兴市| 出国| 尉氏县| 连南| 莱阳市| 砚山县| 盘山县| 和平县| 西林县| 大足县| 北辰区| 尼勒克县| 武邑县| 板桥市| 柞水县| 南岸区| 无为县| 浪卡子县| 遵义市| 科技| 通山县| 瓮安县| 华池县| 沿河| 金平| 武夷山市| 乐平市| 平度市| 泰宁县| 苏尼特右旗| 郑州市| 丹东市| 平定县| 揭西县| 梅河口市| 墨玉县| 万载县| 柞水县| 嘉义县| 策勒县| 祁连县| 长治县| 迁西县| 五峰| 伊宁县| 石泉县| 兴义市| 莲花县| 永宁县| 青海省| 原阳县| 格尔木市| 唐河县| 门源| 通榆县| 晴隆县| 南投县| 朝阳市| 和林格尔县| 徐汇区| 黎川县| 福鼎市| 佳木斯市| 阜城县| 惠水县| 应用必备| 韶山市| 塔城市| 武冈市| 舟曲县| 隆化县| 密云县| 舒兰市| 东光县| 朝阳区| 称多县| 壤塘县| 乐安县| 乐亭县| 浪卡子县| 柘荣县| 千阳县| 黑山县| 吴川市| 榕江县| 鄂温| 阿瓦提县| 松阳县| 长兴县| 慈溪市| 右玉县| 拉萨市| 长沙县| 多伦县| 惠水县| 定南县| 和硕县| 崇礼县| 通山县| 泽库县| 馆陶县| 泗水县| 泾川县| 大埔区| 玉田县| 张北县| 漠河县| 温州市| 永和县| 库车县| 临颍县| 太谷县| 南溪县| 永康市| 洪雅县| 视频| 白城市| 陇川县| 灵武市| 江口县| 黄平县| 鲁甸县| 岚皋县| 清远市| 永靖县| 固阳县| 克拉玛依市| 通海县| 温州市| 额敏县| 南昌市| http://m.bo2020notices.fun http://wap.bo2020hides.fun http://www.gz1980dietc.fun http://www.bo2020contests.fun http://wap.yqo3j7rl9v.fun http://wap.gz1980sellc.fun http://m.gz1980narrowc.fun http://m.bo2020dreazs.fun http://www.yqo5j0rl5v.fun http://wap.yqo6j8rl7v.fun http://m.gz1980definec.fun http://www.bo2020heads.fun http://www.e309ormvl.fun http://www.gz1980puzpc.fun http://wap.gz1980zessagec.fun