社区应用 最新帖子 精华区 社区服务 会员列表 统计排行
  • 628阅读
  • 0回复

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

楼层直达
z3960 
级别: 茶馆馆主
发帖
770867
飞翔币
207694
威望
215657
飞扬币
2511641
信誉值
8


定位+移动选址


百学须先立志—学前须知:


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






尽信书,不如无书—能学到什么?


1、地图状态MapStatus类及监听setOnMapStatusChangeListener
2、定位LocationClient类
3、反地理编码GeoCoder类


工欲善其事必先利其器—申请Key


百度地图访问应用(AK)申请地址:http://lbsyun.baidu.com/apiconsole/key


如果你是第一次申请的话可以参看我的另一篇教程:Android中级篇之百度地图SDK v3.5.0-申请密钥详解[AndroidStudio下获取SHA1]


兵马未动,粮草先行—导入百度地图jar包


1、 进入百度地图API-首页






2、鼠标移动到 开发 标签页上,选择 Android地图SDK






3、选择 相关下载






4、选择 全部下载 (此时这里会跳转到新的下载页面)






5、选择 相对应的开发包(本教程大家选择和下图标注的一样即可)






6、导入jar包到工程


如果你是第一次导入的话可以参看我另一篇教程:Android中级篇之百度地图SDK v3.5.0-配置环境及发布[图解AndroidStudio下配置.so文件] 这里呢就不再赘述了。






权限及服务—AndroidManifest


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.scp">


    <!-- SDK2.1新增获取用户位置信息 -->
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
    <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
    <uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
    <!-- SDK1.5需要android.permission.GET_TASKS权限判断本程序是否为当前运行的应用? -->
    <uses-permission android:name="android.permission.GET_TASKS" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <!-- 这个权限用于进行网络定位-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
    <!-- 这个权限用于访问GPS定位-->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
    <!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
    <!-- 获取运营商信息,用于支持提供运营商信息相关的接口-->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
    <!-- 这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
    <!-- 用于读取手机当前的状态-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
    <!-- 写入扩展存储,向扩展卡写入数据,用于写入离线定位数据-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <!-- 访问网络,网络定位需要上网-->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- SD卡读取权限,用户写入离线定位数据-->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
    <!--允许应用读取低级别的系统日志文件 -->
    <uses-permission android:name="android.permission.READ_LOGS"></uses-permission>
    <!-- 定位所需的权限 -->
    <uses-permission android:name="android.permission.VIBRATE" />


    <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />


    <!--对于很高的分辨率,除采用相应的图片外,还需要加上如下配置,来更好的适配屏幕 -->
    <supports-screens
        android:anyDensity="true"
        android:largeScreens="true"
        android:normalScreens="true"
        android:smallScreens="true" />


    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <meta-data
            android:name="com.baidu.lbsapi.API_KEY"
            android:value="你申请的百度地图KEY" />
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />


                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>


    <service
        android:name="com.baidu.location.f"
        android:enabled="true"
        android:process=":remote">
        <intent-filter>
            <action android:name="com.baidu.location.service_v2.2"></action>
        </intent-filter>
    </service>


</manifest>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73




配置.so文件及其他—build.gradle


apply plugin: 'com.android.application'


android {
    compileSdkVersion 23
    buildToolsVersion "23.0.0"


    defaultConfig {
        applicationId "com.scp"
        minSdkVersion 14
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            //代码混淆
            minifyEnabled false
            //zip优化
            zipAlignEnabled true
            //移除无用的resource文件
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
}


dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.android.support:appcompat-v7:23.0.0'
    compile files('libs/BaiduLBS_Android.jar')
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37




主布局—activity_main.xml


首先我们先分析一下,整个布局结构上面是百度的 MapView (地图区域)下面是一个 ListView(选址列表区域) ,乍一看好像是如下图描述一样:






<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <com.baidu.mapapi.map.MapView
        android:id="@+id/main_bdmap"
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:onClick="true"></com.baidu.mapapi.map.MapView>


    <ListView
        android:id="@+id/main_pois"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"></ListView>


</LinearLayout>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
从布局中我们可以看到 MapView 占了250dp(大家自己可以随意给个值,不要太小即可)。下面的 ListView 则是填充了剩余的空间。


第一步:基础地图


public class MainActivity extends AppCompatActivity {


    private MapView mMapView;
    private BaiduMap mBaiduMap;


    @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();
    }


    @Override
    protected void onResume() {
        super.onResume();
        // activity 恢复时同时恢复地图控件
        mMapView.onResume();
    }


    @Override
    protected void onPause() {
        super.onPause();
        // activity 暂停时同时暂停地图控件
        mMapView.onPause();
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();


        // activity 销毁时同时销毁地图控件
        mMapView.onDestroy();
        mMapView = null;
    }


}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
这里我们的 MainActivity 继承的是 AppCompatActivity,继承 Activity 也行。


//在使用SDK各组件之前初始化context信息,传入ApplicationContext
//注意该方法要再setContentView方法之前实现
SDKInitializer.initialize(getApplicationContext());
1
2
3
这段代码一段要放在 setContentView(R.layout.activity_main); 之前。继续往下看,其中有一句代码requestWindowFeature(Window.FEATURE_NO_TITLE);被注释掉了,需要去掉标题栏的朋友可以加上这句代码。下面呢还有另外一种方法去掉标题栏,打开我们的 style.xml 。






改成 Theme.AppCompat.Light.NoActionBar






运行效果图:






第二步:定位


继续书写我们的MainActivity里面的代码:


public class MainActivity extends AppCompatActivity implements BDLocationListener, OnGetGeoCoderResultListener, BaiduMap.OnMapStatusChangeListener {


    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;


    @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);


        //定义地图状态
        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();


        //创建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<PoiInfo> 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));
    }


    //回退键
    @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;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
代码分段分析:






这里我们放大了地图,zoom(18)【地图缩放级别 3~20】,接下来对我们的定位选项做一个简单的说明:






当我们定位完了之后,我们就可以对定位好的数据进行处理了,简单说明一下我们的定位监听做了哪些事情:






定位好了之后我们进行过反地理编码,下面说明一下反地理编码监听里面做了哪些事情:






PoiAdapter


这里会用到一张图 baidumap_ico_poi_on.png 大家右键另存为就行了:






适配器视图 locationpois.xml :


<?xml version="1.0" encoding="utf-8"?>
<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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
布局简单说明:






实现类 PoiAdapter :


public class PoiAdapter extends BaseAdapter {
    private Context context;
    private List<PoiInfo> pois;
    private LinearLayout linearLayout;




    PoiAdapter(Context context, List<PoiInfo> 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);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
代码分段分析:






地图状态变化—OnMapStatusChangeListener






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






大家移动一下地图试试。


第三步:添加定位图标


更改 activity_main.xml 布局文件:


<?xml version="1.0" encoding="utf-8"?>
<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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38




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






大家移动一下地图试试。


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


首先我们先更改 activity_main.xml :


<?xml version="1.0" encoding="utf-8"?>
<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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
代码说明:






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


<?xml version="1.0" encoding="utf-8"?>
<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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
代码说明:






最终更改我们的 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<PoiInfo> 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<PoiInfo> 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;
    }


}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
代码说明:






最终运行效果与文章开篇展示效果一样,这里呢就不再重复贴图了。
---------------------
作者:cy1笑而过
来源:CSDN
原文:https://blog.csdn.net/y1scp/article/details/49095729
版权声明:本文为博主原创文章,转载请附上博文链接!
 
我不喜欢说话却每天说最多的话,我不喜欢笑却总笑个不停,身边的每个人都说我的生活好快乐,于是我也就认为自己真的快乐。可是为什么我会在一大群朋友中突然地就沉默,为什么在人群中看到个相似的背影就难过,看见秋天树木疯狂地掉叶子我就忘记了说话,看见天色渐晚路上暖黄色的灯火就忘记了自己原来的方向。