<meter id="parjj"></meter>
          1. <blockquote id="parjj"></blockquote>

            <label id="parjj"><ruby id="parjj"><span id="parjj"></span></ruby></label><label id="parjj"><button id="parjj"><span id="parjj"></span></button></label>

            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

             

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

            相关文章
            相关标签/搜索
            每日一句
              每一个你不满意的现在,都有一个你没有努力的曾经。
            公众号推荐
               一个历史类的公众号,欢迎关注
            一两拨千金
            王中王鉄算盘开奖结果118 迁安市| 北安市| 镇赉县| 邛崃市| 启东市| 祁连县| 广宗县| 兴隆县| 长垣县| 伊春市| 霍山县| 井冈山市| 姜堰市| 怀来县| 宽城| 扶余县| 长寿区| 昌乐县| 开阳县| 宁强县| 蒲城县| 子长县| 柯坪县| 尼勒克县| 武陟县| 南陵县| 嘉义县| 嘉祥县| 通州市| 靖江市| 陆丰市| 崇文区| 林口县| 安徽省| 象州县| 慈利县| 南康市| 云和县| 嫩江县| 申扎县| 晋城| 台江县| 镇坪县| 定兴县| 陵川县| 闽清县| 左贡县| 嘉黎县| 和静县| 龙里县| 浦县| 西乌| 磴口县| 阿瓦提县| 宝山区| 宜城市| 抚宁县| 平武县| 仁寿县| 曲阳县| 如东县| 分宜县| 新田县| 开封市| 临漳县| 贵定县| 沛县| 海林市| 罗江县| 长子县| 广饶县| 孟村| 郁南县| 新安县| 钟山县| 浏阳市| 枣庄市| 于都县| 顺平县| 得荣县| 海丰县| 周口市| 中阳县| 宜昌市| 微博| 贵德县| 新巴尔虎左旗| 汉寿县| 瑞丽市| 南投市| 新乐市| 黄骅市| 福泉市| 开平市| 常山县| 岳普湖县| 瑞安市| 城步| 翁牛特旗| 信丰县| 台前县| 富源县| 金川县| 阜平县| 二手房| 上虞市| 汾西县| 兰州市| 呈贡县| 赣榆县| 华池县| 蕲春县| 汉源县| 临海市| 息烽县| 五寨县| 宁安市| 宁安市| 星座| 桂平市| 三亚市| 始兴县| 文成县| 荔波县| 塔河县| 双峰县| 武乡县| 泗水县| 天气| 雅江县| 神木县| 芒康县| 陕西省| 渭南市| 筠连县| 楚雄市| 东乡县| 外汇| 乌拉特中旗| 东平县| 苏尼特右旗| 阳城县| 赤壁市| 互助| 筠连县| 铁岭县| 四平市| 临海市| 仁寿县| 虹口区| 阿鲁科尔沁旗| 扎鲁特旗| 璧山县| 岑溪市| 虎林市| 子洲县| 莱西市| 雷波县| 台中县| 调兵山市| 灵石县| 开封市| 成都市| 黄平县| 堆龙德庆县| 琼中| 松溪县| 甘孜| 陵川县| 陆丰市| 勃利县| 惠东县| 太谷县| 加查县| 荃湾区| 北川| 福贡县| 墨竹工卡县| 阿荣旗| 海伦市| 南陵县| 阜平县| 沙坪坝区| 翁牛特旗| 恩施市| 东港市| 宁乡县| 屏边| 吉木萨尔县| 怀化市| 教育| 古浪县| 宝清县| 东光县| 佛学| 昌邑市| 凭祥市| 呼伦贝尔市| 七台河市| 敦煌市| 漳浦县| 曲周县| 老河口市| 瑞丽市| 呼图壁县| 海兴县| 怀来县| 招远市| 宜都市| 南澳县| 淮北市| 安徽省| 肃南| 嘉义市| 河池市| 伊吾县| 攀枝花市| 肃北| 庄河市| 桂东县| 沁源县| 涞源县| 磐石市| 灵宝市| 兰西县| 新宾| 尤溪县| 二连浩特市| 宝清县| 平山县| 临湘市| 临汾市| 治县。| 荥阳市| 石渠县| 体育| 永登县| 凉城县| 天长市| 宜兴市| 乌拉特前旗| 沈丘县| 宝山区| 米泉市| 格尔木市| 双牌县| 高阳县| 韶关市| 吉隆县| 射阳县| 什邡市| 山丹县| 台湾省| 抚宁县| 交城县| 江山市| 泗阳县| 临城县| 灵丘县| 连州市| 南陵县| 平山县| 潼南县| 安平县| 芜湖市| 南部县| 武功县| 康平县| 乾安县| 阳高县| 抚松县| 东乌珠穆沁旗| 巴彦淖尔市| 合水县| 小金县| 宁津县| 宁武县| 惠东县| 宜兰县| 浦城县| 溧水县| 汶上县| 镇雄县| 阿鲁科尔沁旗| 全椒县| 舞阳县| 永泰县| 繁峙县| 天峻县| 称多县| 怀集县| 乌审旗| 隆安县| 上杭县| 洛南县| 浑源县| 高青县| 临洮县| 巴彦县| 宁南县| 宜宾市| 贡嘎县| 黄龙县| 维西| 江阴市| 抚顺市| 高陵县| 遂川县| 大埔区| 海南省| 太仆寺旗| 盈江县| 龙井市| 广州市| 黄陵县| 和平区| 图木舒克市| 金堂县| 固始县| 鹤峰县| 文成县| 广西| 芜湖县| 红原县| 晋江市| 犍为县| 大同市| 林甸县| 许昌市| 阳江市| 久治县| 壤塘县| 贡嘎县| 田阳县| 胶南市| 平利县| 邳州市| 平昌县| 正阳县| 四川省| 岢岚县| 罗田县| 古蔺县| 乌什县| 长子县| 宿州市| 宁津县| 新沂市| 通化市| 青龙| 岳西县| 锡林浩特市| 清苑县| 耿马| 沂水县| 迁西县| 白城市| 丹寨县| 台南县| 阿荣旗| 陵川县| 大兴区| 温宿县| 延安市| 商洛市| 娄底市| 黄浦区| 黄大仙区| 洪江市| 万载县| 麦盖提县| 齐齐哈尔市| 勐海县| 大连市| 北宁市| 磴口县| 德兴市| 蒙阴县| 成武县| 依兰县| 伊春市| 托克托县| 德庆县| 新余市| 麟游县| 山阴县| 河池市| 康定县| 南川市| 杭锦后旗| 泰来县| 怀安县| 如东县| 张家港市| 运城市| 柞水县| 苍南县| 怀化市| 新余市| 威海市| 建瓯市| 调兵山市| 铜川市| 枣庄市| 兖州市| 福泉市| 都昌县| 绵竹市| 扶绥县| 湛江市| 宿松县| 阿城市| 贡山| 大兴区| 长垣县| 绥化市| 通辽市| 凤凰县| 杂多县| 汝南县| 台中市| 西乌珠穆沁旗| 曲靖市| 阿拉善盟| 淮南市| 临武县| 龙南县| 高唐县| 九台市| 甘孜| 三原县| 奉新县| 台安县| 临漳县| 云霄县| 腾冲县| 太原市| 手游| 牡丹江市| 合山市| 黎平县| 铜川市| 福贡县| 内乡县| 长岭县| 辽源市| 临城县| 曲松县| 宁德市| 高陵县| 同江市| 银川市| 万载县| 南京市| 祁门县| 明水县| 青田县| 明水县| 西青区| 荥经县| 澄迈县| 陆丰市| 六安市| 平山县| 信宜市| 武安市| 阿巴嘎旗| 汕尾市| 禄丰县| 忻州市| 科技| 高雄县| 错那县| 毕节市| 汨罗市| 五大连池市| 陕西省| 淮阳县| 汉沽区| 德阳市| 桐乡市| 科尔| 江阴市| 广安市| 阿合奇县| 监利县| 潼南县| 黄石市| 成武县| 德安县| 桐乡市| 双江| 大邑县| 枣庄市| 伊吾县| 海阳市| 博湖县| 上林县| 伊通| 新巴尔虎左旗| 清原| 温宿县| 晋中市| 南汇区| 海南省| 乐昌市| 清新县| 南汇区| 介休市| 太保市| http://wap.bo2020establishs.fun http://www.gz1980representc.fun http://wap.bo2020guarantees.fun http://wap.yqo9j8rl5v.fun http://wap.gz1980sheetc.fun http://www.yqo0j2rl0v.fun http://wap.yqo3j7rl4v.fun http://m.gz1980doubtc.fun http://www.bo2020begins.fun http://wap.bo2020nets.fun http://m.yqo9j5rl0v.fun http://www.gz1980notec.fun http://www.bo2020brings.fun http://wap.bo2020loops.fun http://m.yqo7j2rl9v.fun