热门标签 | 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地图定位移动选址功能


推荐阅读
  • 深入解析Unity3D游戏开发中的音频播放技术
    在游戏开发中,音频播放是提升玩家沉浸感的关键因素之一。本文将探讨如何在Unity3D中高效地管理和播放不同类型的游戏音频,包括背景音乐和效果音效,并介绍实现这些功能的具体步骤。 ... [详细]
  • 本文探讨了一种常见的C++面试题目——实现自己的String类。通过此过程,不仅能够检验开发者对C++基础知识的掌握程度,还能加深对其高级特性的理解。文章详细介绍了如何实现基本的功能,如构造函数、析构函数、拷贝构造函数及赋值运算符重载等。 ... [详细]
  • 本文介绍了如何通过安装 sqlacodegen 和 pymysql 来根据现有的 MySQL 数据库自动生成 ORM 的模型文件(model.py)。此方法适用于需要快速搭建项目模型层的情况。 ... [详细]
  • 本文探讨了程序员这一职业的本质,认为他们是专注于问题解决的专业人士。文章深入分析了他们的日常工作状态、个人品质以及面对挑战时的态度,强调了编程不仅是一项技术活动,更是个人成长和精神修炼的过程。 ... [详细]
  • 在1995年,Simon Plouffe 发现了一种特殊的求和方法来表示某些常数。两年后,Bailey 和 Borwein 在他们的论文中发表了这一发现,这种方法被命名为 Bailey-Borwein-Plouffe (BBP) 公式。该问题要求计算圆周率 π 的第 n 个十六进制数字。 ... [详细]
  • 本文介绍了SIP(Session Initiation Protocol,会话发起协议)的基本概念、功能、消息格式及其实现机制。SIP是一种在IP网络上用于建立、管理和终止多媒体通信会话的应用层协议。 ... [详细]
  • 二维码的实现与应用
    本文介绍了二维码的基本概念、分类及其优缺点,并详细描述了如何使用Java编程语言结合第三方库(如ZXing和qrcode.jar)来实现二维码的生成与解析。 ... [详细]
  • 在日常生活中,支付宝已成为不可或缺的支付工具之一。本文将详细介绍如何通过支付宝实现免费提现,帮助用户更好地管理个人财务,避免不必要的手续费支出。 ... [详细]
  • 我的读书清单(持续更新)201705311.《一千零一夜》2006(四五年级)2.《中华上下五千年》2008(初一)3.《鲁滨孙漂流记》2008(初二)4.《钢铁是怎样炼成的》20 ... [详细]
  • 本文介绍了如何通过C#语言调用动态链接库(DLL)中的函数来实现IC卡的基本操作,包括初始化设备、设置密码模式、获取设备状态等,并详细展示了将TextBox中的数据写入IC卡的具体实现方法。 ... [详细]
  • 本文详细介绍了C++中的构造函数,包括其定义、特点以及如何通过构造函数进行对象的初始化。此外,还探讨了转换构造函数的概念及其在不同情境下的应用,以及如何避免不必要的隐式类型转换。 ... [详细]
  • 数据类型--char一、char1.1char占用2个字节char取值范围:【0~65535】char采用unicode编码方式char类型的字面量用单引号括起来char可以存储一 ... [详细]
  • 本文详细介绍了iOS应用的生命周期,包括各个状态及其转换过程中的关键方法调用。 ... [详细]
  • 项目风险管理策略与实践
    本文探讨了项目风险管理的关键环节,包括风险管理规划、风险识别、风险分析(定性和定量)、风险应对策略规划及风险控制。旨在通过系统的方法提升项目成功率,减少不确定因素对项目的影响。 ... [详细]
  • 探索AI智能机器人自动盈利系统的构建
    用户可通过支付198元押金及30元设备维护费租赁AI智能机器人,推荐他人加入可获得相应佣金。随着推荐人数的增加,用户将逐步解锁更高版本,享受更多收益。 ... [详细]
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社区 版权所有