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


推荐阅读
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 本文介绍了指针的概念以及在函数调用时使用指针作为参数的情况。指针存放的是变量的地址,通过指针可以修改指针所指的变量的值。然而,如果想要修改指针的指向,就需要使用指针的引用。文章还通过一个简单的示例代码解释了指针的引用的使用方法,并思考了在修改指针的指向后,取指针的输出结果。 ... [详细]
  • 在project.properties添加#Projecttarget.targetandroid-19android.library.reference.1..Sliding ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • 本文介绍了一种解析GRE报文长度的方法,通过分析GRE报文头中的标志位来计算报文长度。具体实现步骤包括获取GRE报文头指针、提取标志位、计算报文长度等。该方法可以帮助用户准确地获取GRE报文的长度信息。 ... [详细]
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社区 版权所有