热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android中级篇之百度地图SDKv3.5.0一步一步带你仿各大主流APP地图定位移动选址功能

定位+移动选址百学须先立志—学前须知:我们经常在各大主流APP上要求被写上地址,如百度外卖、爱鲜蜂收货地址等等;其中他们大多数是可以让我们在地图上移动选址。就如下面这段GIF演示

定位+移动选址
  • 百学须先立志—学前须知:

    我们经常在各大主流APP上要求被写上地址,如百度外卖、爱鲜蜂收货地址等等;其中他们大多数是可以让我们在地图上移动选址。就如下面这段GIF演示的一样:

    技术分享

    适配器视图 locationpois.xml

    
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingLeft="5dp">
    
        <LinearLayout
            android:id="@+id/locationpois_linearlayout"
            android:gravity="center_vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
    
            <TextView
                android:id="@+id/locationpois_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        LinearLayout>
    
        <TextView
            android:id="@+id/locationpois_address"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    
    LinearLayout>

    布局简单说明:

    技术分享

    实现类 PoiAdapter

    public class PoiAdapter extends BaseAdapter {
        private Context context;
        private List pois;
        private LinearLayout linearLayout;
    
    
        PoiAdapter(Context context, List pois) {
            this.cOntext= context;
            this.pois = pois;
        }
    
        @Override
        public int getCount() {
            return pois.size();
        }
    
        @Override
        public Object getItem(int position) {
            return pois.get(position);
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            if (cOnvertView== null) {
                cOnvertView= LayoutInflater.from(context).inflate(R.layout.locationpois_item, null);
                linearLayout = (LinearLayout) convertView.findViewById(R.id.locationpois_linearlayout);
                holder = new ViewHolder(convertView);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
            if (position == 0 && linearLayout.getChildCount() <2) {
                ImageView imageView = new ImageView(context);
                ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(32, 32);
                imageView.setLayoutParams(params);
                imageView.setBackgroundColor(Color.TRANSPARENT);
                imageView.setImageResource(R.mipmap.baidumap_ico_poi_on);
                imageView.setScaleType(ImageView.ScaleType.FIT_XY);
                linearLayout.addView(imageView, 0, params);
                holder.locationpoi_name.setTextColor(Color.parseColor("#FF5722"));
            }
            PoiInfo poiInfo = pois.get(position);
            holder.locationpoi_name.setText(poiInfo.name);
            holder.locationpoi_address.setText(poiInfo.address);
            return convertView;
        }
    
        class ViewHolder {
            TextView locationpoi_name;
            TextView locationpoi_address;
    
            ViewHolder(View view) {
                locationpoi_name = (TextView) view.findViewById(R.id.locationpois_name);
                locationpoi_address = (TextView) view.findViewById(R.id.locationpois_address);
            }
        }
    }

    代码分段分析:

    技术分享

  • 地图状态变化—OnMapStatusChangeListener

    技术分享

    来看看我们现在运行是什么样子的:

    技术分享

    大家移动一下地图试试。

  • 第三步:添加定位图标

    更改 activity_main.xml 布局文件:

    
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
    
            <RelativeLayout
                android:id="@+id/main_top_RL"
                android:layout_width="match_parent"
                android:layout_height="250dp">
    
                <com.baidu.mapapi.map.MapView
                    android:id="@+id/main_bdmap"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:onClick="true">com.baidu.mapapi.map.MapView>
    
                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:background="@android:color/transparent"
                    android:src="@mipmap/baidumap_ico_poi_on" />
            RelativeLayout>
    
            <ListView
                android:id="@+id/main_pois"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1">ListView>
        LinearLayout>
    
    LinearLayout>

    技术分享

    此次没有任何实现代码添加或者改动,运行看一下效果:

    技术分享

    大家移动一下地图试试。

  • 输入关键字显示相关地址列表

    首先我们先更改 activity_main.xml

    
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
    
            <RelativeLayout
                android:id="@+id/main_top_RL"
                android:layout_width="match_parent"
                android:layout_height="250dp">
    
                <com.baidu.mapapi.map.MapView
                    android:id="@+id/main_bdmap"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:onClick="true">com.baidu.mapapi.map.MapView>
    
                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:background="@android:color/transparent"
                    android:src="@mipmap/baidumap_ico_poi_on" />
            RelativeLayout>
    
            <ListView
                android:id="@+id/main_pois"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1">ListView>
        LinearLayout>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="40dp"
                android:background="#ffcccccc"
                android:gravity="center"
                android:orientation="horizontal">
    
                <EditText
                    android:id="@+id/main_search_address"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:background="@android:color/transparent"
                    android:hint="请输入地址" />
    
            LinearLayout>
    
            <ListView
                android:id="@+id/main_search_pois"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:background="#ffcccccc"
                android:visibility="gone">ListView>
        LinearLayout>
    
    
    RelativeLayout>

    代码说明:

    技术分享

    接下来书写适配器的item布局 poisearch_item.xml

    
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <TextView
            android:id="@+id/poisearch_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
    
            <TextView
                android:id="@+id/poisearch_address"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1" />
    
            <TextView
                android:id="@+id/poisearch_distance"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        LinearLayout>
    
    LinearLayout>

    代码说明:

    技术分享

    最终更改我们的 MainActivity 里面的代码 (请结合下面代码说明来看)

    public class MainActivity extends AppCompatActivity implements BDLocationListener, OnGetGeoCoderResultListener, 
    
    BaiduMap.OnMapStatusChangeListener, TextWatcher {
    
        private MapView mMapView;
        private BaiduMap mBaiduMap;
        private ListView poisLL;
        /**
         * 定位模式
         */
        private MyLocationConfiguration.LocationMode mCurrentMode;
        /**
         * 定位端
         */
        private LocationClient mLocClient;
        /**
         * 是否是第一次定位
         */
        private boolean isFirstLoc = true;
        /**
         * 定位坐标
         */
        private LatLng locationLatLng;
        /**
         * 定位城市
         */
        private String city;
        /**
         * 反地理编码
         */
        private GeoCoder geoCoder;
        /**
         * 界面上方布局
         */
        private RelativeLayout topRL;
        /**
         * 搜索地址输入框
         */
        private EditText searchAddress;
        /**
         * 搜索输入框对应的ListView
         */
        private ListView searchPois;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            //在使用SDK各组件之前初始化context信息,传入ApplicationContext
            //注意该方法要再setContentView方法之前实现
            SDKInitializer.initialize(getApplicationContext());
            //requestWindowFeature(Window.FEATURE_NO_TITLE);
            setContentView(R.layout.activity_main);
            initView();
        }
    
        private void initView() {
            mMapView = (MapView) findViewById(R.id.main_bdmap);
            mBaiduMap = mMapView.getMap();
    
            poisLL = (ListView) findViewById(R.id.main_pois);
    
            topRL = (RelativeLayout) findViewById(R.id.main_top_RL);
    
            searchAddress = (EditText) findViewById(R.id.main_search_address);
    
            searchPois = (ListView) findViewById(R.id.main_search_pois);
    
            //定义地图状态
            MapStatus mMapStatus = new MapStatus.Builder().zoom(18).build();
            MapStatusUpdate mMapStatusUpdate = MapStatusUpdateFactory.newMapStatus(mMapStatus);
            //改变地图状态
            mBaiduMap.setMapStatus(mMapStatusUpdate);
    
            //地图状态改变相关监听
            mBaiduMap.setOnMapStatusChangeListener(this);
    
            //开启定位图层
            mBaiduMap.setMyLocationEnabled(true);
    
            //定位图层显示方式
            mCurrentMode = MyLocationConfiguration.LocationMode.NORMAL;
    
            /**
             * 设置定位图层配置信息,只有先允许定位图层后设置定位图层配置信息才会生效
             * customMarker用户自定义定位图标
             * enableDirection是否允许显示方向信息
             * locationMode定位图层显示方式
             */
            mBaiduMap.setMyLocationConfigeration(new MyLocationConfiguration(mCurrentMode, true, null));
    
            //初始化定位
            mLocClient = new LocationClient(this);
            //注册定位监听
            mLocClient.registerLocationListener(this);
    
            //定位选项
            LocationClientOption option = new LocationClientOption();
            /**
             * coorType - 取值有3个:
             * 返回国测局经纬度坐标系:gcj02
             * 返回百度墨卡托坐标系 :bd09
             * 返回百度经纬度坐标系 :bd09ll
             */
            option.setCoorType("bd09ll");
            //设置是否需要地址信息,默认为无地址
            option.setIsNeedAddress(true);
            //设置是否需要返回位置语义化信息,可以在BDLocation.getLocationDescribe()中得到数据,ex:"在天安门附近", 可以用作地址信息的补充
            option.setIsNeedLocationDescribe(true);
            //设置是否需要返回位置POI信息,可以在BDLocation.getPoiList()中得到数据
            option.setIsNeedLocationPoiList(true);
            /**
             * 设置定位模式
             * Battery_Saving
             * 低功耗模式
             * Device_Sensors
             * 仅设备(Gps)模式
             * Hight_Accuracy
             * 高精度模式
             */
            option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
            //设置是否打开gps进行定位
            option.setOpenGps(true);
            //设置扫描间隔,单位是毫秒 当<1000(1s)时,定时定位无效
            option.setScanSpan(1000);
    
            //设置 LocationClientOption
            mLocClient.setLocOption(option);
    
            //开始定位
            mLocClient.start();
    
        }
    
        /**
         * 定位监听
         *
         * @param bdLocation
         */
        @Override
        public void onReceiveLocation(BDLocation bdLocation) {
    
            //如果bdLocation为空或mapView销毁后不再处理新数据接收的位置
            if (bdLocation == null || mBaiduMap == null) {
                return;
            }
    
            //定位数据
            MyLocationData data = new MyLocationData.Builder()
                    //定位精度bdLocation.getRadius()
                    .accuracy(bdLocation.getRadius())
                            //此处设置开发者获取到的方向信息,顺时针0-360
                    .direction(bdLocation.getDirection())
                            //经度
                    .latitude(bdLocation.getLatitude())
                            //纬度
                    .longitude(bdLocation.getLongitude())
                            //构建
                    .build();
    
            //设置定位数据
            mBaiduMap.setMyLocationData(data);
    
            //是否是第一次定位
            if (isFirstLoc) {
                isFirstLoc = false;
                LatLng ll = new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude());
                MapStatusUpdate msu = MapStatusUpdateFactory.newLatLngZoom(ll, 18);
                mBaiduMap.animateMapStatus(msu);
            }
    
            //获取坐标,待会用于POI信息点与定位的距离
            locatiOnLatLng= new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude());
            //获取城市,待会用于POISearch
            city = bdLocation.getCity();
    
            //文本输入框改变监听,必须在定位完成之后
            searchAddress.addTextChangedListener(this);
    
            //创建GeoCoder实例对象
            geoCoder = GeoCoder.newInstance();
            //发起反地理编码请求(经纬度->地址信息)
            ReverseGeoCodeOption reverseGeoCodeOption = new ReverseGeoCodeOption();
            //设置反地理编码位置坐标
            reverseGeoCodeOption.location(new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude()));
            geoCoder.reverseGeoCode(reverseGeoCodeOption);
    
            //设置查询结果监听者
            geoCoder.setOnGetGeoCodeResultListener(this);
        }
    
        //地理编码查询结果回调函数
        @Override
        public void onGetGeoCodeResult(GeoCodeResult geoCodeResult) {
        }
    
        //反地理编码查询结果回调函数
        @Override
        public void onGetReverseGeoCodeResult(ReverseGeoCodeResult reverseGeoCodeResult) {
            List poiInfos = reverseGeoCodeResult.getPoiList();
            PoiAdapter poiAdapter = new PoiAdapter(MainActivity.this, poiInfos);
            poisLL.setAdapter(poiAdapter);
        }
    
    
        /**
         * 手势操作地图,设置地图状态等操作导致地图状态开始改变
         *
         * @param mapStatus 地图状态改变开始时的地图状态
         */
        @Override
        public void onMapStatusChangeStart(MapStatus mapStatus) {
        }
    
        /**
         * 地图状态变化中
         *
         * @param mapStatus 当前地图状态
         */
        @Override
        public void onMapStatusChange(MapStatus mapStatus) {
        }
    
        /**
         * 地图状态改变结束
         *
         * @param mapStatus 地图状态改变结束后的地图状态
         */
        @Override
        public void onMapStatusChangeFinish(MapStatus mapStatus) {
            //地图操作的中心点
            LatLng cenpt = mapStatus.target;
            geoCoder.reverseGeoCode(new ReverseGeoCodeOption().location(cenpt));
        }
    
        /**
         * 输入框监听---输入之前
         *
         * @param s     字符序列
         * @param start 开始
         * @param count 总计
         * @param after 之后
         */
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }
    
        /**
         * 输入框监听---正在输入
         *
         * @param s      字符序列
         * @param start  开始
         * @param before 之前
         * @param count  总计
         */
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        }
    
        /**
         * 输入框监听---输入完毕
         *
         * @param s
         */
        @Override
        public void afterTextChanged(Editable s) {
            if (s.length() == 0 || "".equals(s.toString())) {
                searchPois.setVisibility(View.GONE);
            } else {
                //创建PoiSearch实例
                PoiSearch poiSearch = PoiSearch.newInstance();
                //城市内检索
                PoiCitySearchOption poiCitySearchOption = new PoiCitySearchOption();
                //关键字
                poiCitySearchOption.keyword(s.toString());
                //城市
                poiCitySearchOption.city(city);
                //设置每页容量,默认为每页10条
                poiCitySearchOption.pageCapacity(10);
                //分页编号
                poiCitySearchOption.pageNum(1);
                poiSearch.searchInCity(poiCitySearchOption);
                //设置poi检索监听者
                poiSearch.setOnGetPoiSearchResultListener(new OnGetPoiSearchResultListener() {
                    //poi 查询结果回调
                    @Override
                    public void onGetPoiResult(PoiResult poiResult) {
                        List poiInfos = poiResult.getAllPoi();
                        PoiSearchAdapter poiSearchAdapter = new PoiSearchAdapter(MainActivity.this, poiInfos, locationLatLng);
                        searchPois.setVisibility(View.VISIBLE);
                        searchPois.setAdapter(poiSearchAdapter);
                    }
    
                    //poi 详情查询结果回调
                    @Override
                    public void onGetPoiDetailResult(PoiDetailResult poiDetailResult) {
                    }
                });
            }
        }
    
    
        //回退键
        @Override
        public void onBackPressed() {
            finish();
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            // activity 恢复时同时恢复地图控件
            mMapView.onResume();
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            // activity 暂停时同时暂停地图控件
            mMapView.onPause();
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
    
            //退出时停止定位
            mLocClient.stop();
            //退出时关闭定位图层
            mBaiduMap.setMyLocationEnabled(false);
    
            // activity 销毁时同时销毁地图控件
            mMapView.onDestroy();
    
            //释放资源
            if (geoCoder != null) {
                geoCoder.destroy();
            }
    
            mMapView = null;
        }
    
    }

    代码说明:

    技术分享

    最终运行效果与文章开篇展示效果一样,这里呢就不再重复贴图了。

  • GitHub

    最终项目GitHub地址:https://github.com/scp504677840/MoveMapLocation.git

版权声明:本文为博主原创文章,未经博主允许不得转载。

Android中级篇之百度地图SDK v3.5.0-一步一步带你仿各大主流APP地图定位移动选址功能


推荐阅读
  • C#设计模式学习笔记:观察者模式解析
    本文将探讨观察者模式的基本概念、应用场景及其在C#中的实现方法。通过借鉴《Head First Design Patterns》和维基百科等资源,详细介绍该模式的工作原理,并提供具体代码示例。 ... [详细]
  • 在使用STM32Cube进行定时器配置时,有时会遇到延时不准的问题。本文探讨了可能导致延时不准确的原因,并提供了解决方法和预防措施。 ... [详细]
  • 深入理解Lucene搜索机制
    本文旨在帮助读者全面掌握Lucene搜索的编写步骤、核心API及其应用。通过详细解析Lucene的基本查询和查询解析器的使用方法,结合架构图和代码示例,带领读者深入了解Lucene搜索的工作流程。 ... [详细]
  • 在项目部署后,Node.js 进程可能会遇到不可预见的错误并崩溃。为了及时通知开发人员进行问题排查,我们可以利用 nodemailer 插件来发送邮件提醒。本文将详细介绍如何配置和使用 nodemailer 实现这一功能。 ... [详细]
  • Appium + Java 自动化测试中处理页面空白区域点击问题
    在进行移动应用自动化测试时,有时会遇到某些页面没有返回按钮,只能通过点击空白区域返回的情况。本文将探讨如何在Appium + Java环境中有效解决此类问题,并提供详细的解决方案。 ... [详细]
  • 如何清除Chrome浏览器地址栏的特定历史记录
    在使用Chrome浏览器时,你可能会发现地址栏保存了大量浏览记录。有时你可能希望删除某些特定的历史记录而不影响其他数据。本文将详细介绍如何单独删除地址栏中的特定记录以及批量清除所有历史记录的方法。 ... [详细]
  • 利用Selenium与ChromeDriver实现豆瓣网页全屏截图
    本文介绍了一种使用Selenium和ChromeDriver结合Python代码,轻松实现对豆瓣网站进行完整页面截图的方法。该方法不仅简单易行,而且解决了新版Selenium不再支持PhantomJS的问题。 ... [详细]
  • 嵌入式开发环境搭建与文件传输指南
    本文详细介绍了如何为嵌入式应用开发搭建必要的软硬件环境,并提供了通过串口和网线两种方式将文件传输到开发板的具体步骤。适合Linux开发初学者参考。 ... [详细]
  • 解决TensorFlow CPU版本安装中的依赖问题
    本文记录了在安装CPU版本的TensorFlow过程中遇到的依赖问题及解决方案,特别是numpy版本不匹配和动态链接库(DLL)错误。通过详细的步骤说明和专业建议,帮助读者顺利安装并使用TensorFlow。 ... [详细]
  • 探索新一代API文档工具,告别Swagger的繁琐
    对于后端开发者而言,编写和维护API文档既繁琐又不可或缺。本文将介绍一款全新的API文档工具,帮助团队更高效地协作,简化API文档生成流程。 ... [详细]
  • 本文探讨了在构建应用程序时,如何对不同类型的数据进行结构化设计。主要分为三类:全局配置、用户个人设置和用户关系链。每种类型的数据都有其独特的用途和应用场景,合理规划这些数据结构有助于提升用户体验和系统的可维护性。 ... [详细]
  • Linux中的yum安装软件
    yum俗称大黄狗作用:解决安装软件包的依赖关系当安装依赖关系的软件包时,会将依赖的软件包一起安装。本地yum:需要yum源,光驱挂载。yum源:(刚开始查看yum源中的内容就是上图 ... [详细]
  • 鼠标悬停出现提示信息怎么做
    概述–提示:指启示,提起注意或给予提醒和解释。在excel中会经常用到给某个格子增加提醒信息,比如金额提示输入数值或最大长度值等等。设置方式也有多种,简单的,仅为单元格插入批注就可 ... [详细]
  • 气象对比分析
    本文探讨了不同地区和时间段的天气模式,通过详细的图表和数据分析,揭示了气候变化的趋势及其对环境和社会的影响。 ... [详细]
  • 探讨 HDU 1536 题目,即 S-Nim 游戏的博弈策略。通过 SG 函数分析游戏胜负的关键,并介绍如何编程实现解决方案。 ... [详细]
author-avatar
拍友2502902623
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有