搜索
 找回密码
 立即注册

简单一步 , 微信登陆

百度地图开发(三)之地图控制 + 定位

作者:liuwei | 时间:2016-9-28 12:28:36 | 阅读:3528| 只看该作者

    前两篇关于百度地图的blog写的是,一些基本图层的展示 和 覆盖物的添加+地理编码和反地理编码。
    接下来,这篇blog主要说一些关于地图控制方面的内容和定位功能。
    百度地图提供的关于地图的操作主要有:单击、双击、长按、缩放、旋转、俯视等。
地图控制
    我们现在已经知道,想要显示一个地图,只需要在xml文件中添加一个MapView控件即可,但是想要对其进行一些控制,就需要通过这个控件返回一个BaiduMap对象。
从API中先看一下MapView的方法:

    对于MapView这个类,官方解释是一个显示地图的视图,负责从服务器端获取地图数据,并且会捕捉到屏幕触控手势事件。使用这个类必须按照它的生命周期进行操作,从上图可以看到,它包括一些类似于activity生命周期的方法:onResume()、onPause()、onDestory()。所以我们需要在activity的各个生命周期中,把MapView的各个生命周期函数添加进去。
    在使用地图控件之前必须调用SDKInitializer.initialize(Context)函数用以提供全局Context信息。
    默认情况下,地图显示的时候会带着原生的缩放控件:。还有比例尺控件:。
通过showZoomControls(booleanshow)showScaleControl(booleanshow)这两个方法可以设置显示或者不显示两个控件。还可以通过设置setxxxPosition(Pointp)方法来设置控件的位置。
[java] view plaincopyfile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image008.giffile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image009.gif
1.   mapView.showZoomControls(false);// 不显示默认的缩放控件  
2.   mapView.showScaleControl(false);// 不显示默认比例尺控件  
   要想实现地图的一些控制,就需要使用到BaiduMap,这个类是专门用来操作地图控件的。
    上面的四个接口就是用来对地图添加相应的事件的。我们主要看一下下面的两个方法,它们都是以动画的方式更新地图状态。不同的是一个可以指定时长,另一个有默认的动画耗时。
    参数MapStatusUpdate描述的是地图状态将要发生的变化。也就是说,要想改变地图的某些状态,需要构造出一个MapStatusUpdate对象,然后使用animateMapStatus()方法来更新地图状态。但是并没有在API中找到它的相关的构造方法。但是在com.baidu.mapapi.map包下面找到了对应的"工厂类"。

    打开MapStatusUpdateFactory可以看到很多静态的方法:

    通过这些静态的方法能够构造出各种类型的MapStatusUpdate对象。
   zoomIn()和zoomOut()分别是放大和缩小地图,分别是在当前基础上增加或较少1个级别。zoomTo()可以自己设置某一个缩放级别。百度地图将地图的级别定义为【3~19】。
放大:
[java] view plaincopyfile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image008.giffile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image009.gif
1.   msu = msuFactory.zoomIn();  
2.   bdMap.animateMapStatus(msu);  
缩小:
[java] view plaincopyfile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image008.giffile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image009.gif
1.   msu = msuFactory.zoomOut();  
2.   bdMap.animateMapStatus(msu);  
设置地图中心点:
[java] view plaincopyfile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image008.giffile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image009.gif
1.   msu = msuFactory.newLatLng(arg0);  
2.   bdMap.animateMapStatus(msu);  
   其他的方法就不一一叙述了。
    关于地图控制状态的还有两个类:MapStatusMapStatus.Builder。Builder是MapStatus的一个内部类,用于构造它,我们在API中可以看到MapStatus中是没有构造函数的。

    使用这两个类可以对地图进行旋转、俯视、设置中心点、设置缩放级别等操作。通过这些方法构造出MapStatus方法之后,怎么让BaiduMap调用它呢?
    查阅BaiduMap的所有方法之后也没有找到参数是MapStatus的方法。那么,猜想可能是通过把MapStatus转换成一个其他的对象,然后在由BaiduMap调用。而BaiduMap只有animateMapStatus()方法来更新地图状态。所以很定是MapStatus--->MapStatusUpdate。在MSU的工厂类中有这样一个方法:newMapStatus(MapStatusmapStatus)。OK,通过这个方法,可以把构造的MapStatus对象转成MapStatusUpdate,然后在通过animateMapStatus()调用就行了。
旋转:
[java] view plaincopyfile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image008.giffile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image009.gif
1.   mapStatus = new MapStatus.Builder(bdMap.getMapStatus()).rotate(rotateAngle += 30).build();  
2.   msu = msuFactory.newMapStatus(mapStatus);  
3.   bdMap.animateMapStatus(msu);  
俯视(-45°~0)
[java] view plaincopyfile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image008.giffile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image009.gif
1.   mapStatus = new MapStatus.Builder(bdMap.getMapStatus()).overlook(overlookAngle -= 10).build();  
2.   msu = msuFactory.newMapStatus(mapStatus);  
3.   bdMap.animateMapStatus(msu);  
   这里,lz有一个疑问:MapStaus.Builder中有一个设置地图中心点的方法:
,在MapStatusUpdateFactory中也有一个设置中心点的方法:。连个都是设置中心点,不知道区别是什么?希望知道的给我留个言,告知一下!!谢谢!~~
截屏:
    在BaiduMap中有一个截屏的回调接口和一个截图的请求方法

很明显,调用这个截图请求方法,参数是上面的回调接口。在回调接口中只有一个方法:**napshotReady(Bitmap snapshot)。我们得到这个bitmap之后,就可以生成图片保存起来了。
    有Bitmap转成图片就需要用到Bitmap.compress()方法:
[java] view plaincopyfile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image008.giffile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image009.gif
1.   bdMap.snapshot(new SnapshotReadyCallback() {  
2.           @Override  
3.           public void **napshotReady(Bitmap bitmap) {  
4.               File file = new File("/mnt/sdcard/test.png");  
5.               FileOutputStream out;  
6.               try {  
7.                   out = new FileOutputStream(file);  
8.                   if (bitmap.compress(  
9.                           Bitmap.CompressFormat.PNG, 100, out)) {  
10.                      out.flush();  
11.                      out.close();  
12.                  }  
13.                  Toast.makeText(MapControllActivity.this,  
14.                          "屏幕截图成功,图片存在: " + file.toString(),  
15.                          Toast.LENGTH_SHORT).show();  
16.              } catch (FileNotFoundException e) {  
17.                  e.printStackTrace();  
18.              } catch (IOException e) {  
19.                  e.printStackTrace();  
20.              }  
21.          }  
22.      });  
定位
    LZ采用的是百度最新版本5.0的SDK,该版本支持全球定位。
    开发定位功能一般都是按照以下步骤:
1. 导入库文件。
    下载下来lib压缩包之后,会看到很多文件夹(对应很多架构),官方建议全部拷贝到lib下,这样程序兼容性大大提升,不要忘了把locSDK_5.0.jar拷贝到lib下。
2. 添加定位service
[html] view plaincopyfile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image008.giffile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image009.gif
1.   <service  
2.           android:name="com.baidu.location.f"  
3.           android:enabled="true"  
4.           android:process=":remote" >  
5.   </service>  
3.添加权限
[html] view plaincopyfile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image008.giffile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image009.gif
1.   <!-- 这个权限用于进行网络定位 -->  
2.       <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" >  
3.       </uses-permission>  
4.       <!-- 这个权限用于访问GPS定位 -->  
5.       <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" >  
6.       </uses-permission>  
7.       <!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位 -->  
8.       <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" >  
9.       </uses-permission>  
10.      <!-- 获取运营商信息,用于支持提供运营商信息相关的接口 -->  
11.      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >  
12.      </uses-permission>  
13.      <!-- 这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位 -->  
14.      <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" >  
15.      </uses-permission>  
16.      <!-- 用于读取手机当前的状态 -->  
17.      <uses-permission android:name="android.permission.READ_PHONE_STATE" >  
18.      </uses-permission>  
19.      <!-- 写入扩展存储,向扩展卡写入数据,用于写入离线定位数据 -->  
20.      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >  
21.      </uses-permission>  
22.      <!-- 访问网络,网络定位需要上网 -->  
23.      <uses-permission android:name="android.permission.INTERNET" />  
24.      <!-- SD卡读取权限,用户写入离线定位数据 -->  
25.      <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" >  
26.      </uses-permission>  
27.      <!-- 允许应用读取低级别的系统日志文件 -->  
28.      <uses-permission android:name="android.permission.READ_LOGS" >  
29.      </uses-permission>  
4.编写定位程序
    这一步才是重点。百度地图可以使用GPS和网络定位(WIFI和基站)进行定位。基本定位功能还支持定位结果的反地理编码功能,离线定位,位置提醒功能和地理围栏功能。
    主要会用到LocationClient、BDLocationListener、BDNotifyListener、LocationClientOption等类。
    (1)初始化LocationClient类:
   LocationClient类是定位SDK的核心类,必须在主线程中声明。需要传入一个Context类型的参数,推荐使用getApplicationContext()来获取全局进程有效的context。
    主要会用到该类中的以下几个方法:
   (2)设置定位参数:
    主要的参数有:定位模式、返回坐标类型、是否打开GPS等。
定位模式分为三种:
1. 高精度定位模式:同时使用网络定位和GPS定位,优先返回最高精度的定位结果。
2. 低功耗定位模式:不使用GPS,只使用网络定位(WiFi和基站)。
3. 仅用设备定位模式: 不适用网络定位,只使用GPS进行定位。但是此模式下不支持室内环境的定位。

    在API中主要关注“setxxx”类型的函数。主要用到红色框标注的方法。
[java] view plaincopyfile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image008.giffile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image009.gif
1.   LocationClientOption locOption = new LocationClientOption();  
2.           locOption.setLocationMode(LocationMode.Hight_Accuracy);// 设置定位模式  
3.           locOption.setCoorType("bd09ll");// 设置定位结果类型  
4.           locOption.setScanSpan(5000);// 设置发起定位请求的间隔时间,ms  
5.           locOption.setIsNeedAddress(true);// 返回的定位结果包含地址信息  
6.           locOption.setNeedDeviceDirect(true);// 设置返回结果包含手机的方向  
7.     
8.           locationClient.setLocOption(locOption);  
   坐标类型分为三种:国测局经纬度坐标系(gcj02),百度墨卡托坐标系(bd09),百度经纬度坐标系(bd09ll)。

[java] view plaincopyfile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image008.giffile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image009.gif
1.   locationClient.registerLocationListener(locationListener);  
2.   //  
3.   class MyLocationListener implements BDLocationListener {  
4.           // 异步返回的定位结果  
5.           @Override  
6.           public void onReceiveLocation(BDLocation location) {  
7.       }  
8.   }  
    百度官网说明有一些是不准确的。实现BDLocationListener接口的时候,在之前的版本是有两个方法需要实现,新版本(5.0)的只有一个方法需要实现:onReceiveLocation()。BDLocation类封装了定位SDK的定位结果,通过该可以获取定位返回的结果、位置坐标、精度半径等信息。

    定位成功与否,定位的错误码都是通过getLocType()这个方法得到的,返回值是int类型。

   注意:只有在使用网络定位的情况下,才能获取当前位置的反地理编码。
[java] view plaincopy
1.   } else if (locType == BDLocation.TypeNetWorkLocation) {  
2.                   addrStr = location.getAddrStr();// 获取反地理编码(文字描述的地址)  
3.                   Toast.makeText(LocationActivity.this, addrStr,  
4.                           Toast.LENGTH_SHORT).show();  
5.               }  
   (4)添加位置提醒**函数
[java] view plaincopy
1.   notifyListener = new MyNotifyListener();  
2.   notifyListener.SetNotifyLocation(longitude, latitude, 3000, "bd09ll");//精度,维度,范围,坐标类型  
3.   locationClient.registerNotify(notifyListener);  
[java] view plaincopyfile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image008.giffile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image009.gif
1.   /**
2.        * 位置提醒**器
3.        * @author ys
4.        *
5.        */  
6.       class MyNotifyListener extends BDNotifyListener {  
7.           @Override  
8.           public void onNotify(BDLocation bdLocation, float distance) {  
9.               super.onNotify(bdLocation, distance);  
10.              mVibrator.vibrate(1000);//振动提醒已到设定位置附近  
11.              Toast.makeText(LocationActivity.this, "震动提醒", Toast.LENGTH_SHORT).show();  
12.          }  
13.      }  
   (5)开启定位
    LocationClient的start()方法用来启动定位SDK,requestLocation()方法用来请求一次定位,请求过程是异步的。调用start()方法之后,会根据你设置的定位事件间隔来请求定位。
    (6)最后不要忘了在不用的时候注销定位**和位置提醒**,并且关闭地图。
[java] view plaincopyfile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image008.giffile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image009.gif
1.   @Override  
2.       protected void onDestroy() {  
3.           super.onDestroy();  
4.           mapview.onDestroy();  
5.           locationClient.unRegisterLocationListener(locationListener);  
6.           //取消位置提醒  
7.           locationClient.removeNotifyEvent(notifyListener);  
8.           locationClient.stop();  
9.       }  
   此时可以完成了一个基本的地图定位功能和位置提醒。如果要显示在地图上,就想百度那样出现一个点表示地图的定位点,就需要用到MyLocationConfiguration(配置定位图层显示方式)MylocationData(定位数据)
    MyLocationData包含一个内部了Builder用于构建MyLocationData对象:
[java] view plaincopyfile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image008.giffile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image009.gif
1.   // 构造定位数据  
2.               MyLocationData locData = new MyLocationData.Builder()  
3.                       .accuracy(radius)//  
4.                       .direction(direction)// 方向  
5.                       .latitude(latitude)//  
6.                       .longitude(longitude)//  
7.                       .build();  
8.               // 设置定位数据  
9.               bdMap.setMyLocationData(locData);  
   通过定位的onReceiveLocation()方法可以得到定位的经纬度,然后可以通过animationMapStatus()方法把定位到的点移动到地图中心。
[java] view plaincopyfile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image008.giffile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image009.gif
1.   LatLng ll = new LatLng(latitude, longitude);  
2.               MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(ll);  
3.               bdMap.animateMapStatus(msu);  
   定位图层的显示方式有三种:普通、跟随、罗盘,在MyLocationConfiguration.LocationMode这个内部类中定义为枚举常量。

    我们来看一下MyLocationConfiguration的构造函数:

    第一个参数就是图层的显示方式(LocationMode类型),第二个参数表示是否显示方向信息(booleab类型),第三个参数是(bitmapDescriptor类型,我们在前面的blog有过介绍了)。构造出这个对象之后,就可以调用BaiduMap的setMyLocationConfigeration()方法来设置定位图层配置信息了。

[java] view plaincopyfile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image008.giffile:///C:/Users/liuwei/AppData/Local/Temp/msohtmlclip1/01/clip_image009.gif
1.   switch (currentMode) {  
2.               case NORMAL:  
3.                   locateBtn.setText("跟随");  
4.                   currentMode = MyLocationConfiguration.LocationMode.FOLLOWING;  
5.                   break;  
6.               case FOLLOWING:  
7.                   locateBtn.setText("罗盘");  
8.                   currentMode = MyLocationConfiguration.LocationMode.COMPASS;  
9.                   break;  
10.              case COMPASS:  
11.                  locateBtn.setText("普通");  
12.                  currentMode = MyLocationConfiguration.LocationMode.NORMAL;  
13.                  break;  
14.              }  
15.              bdMap.setMyLocationConfigeration(new MyLocationConfiguration(  
16.                      currentMode, true, currentMarker));  
总结
    OK,本篇blog主要讲解了地图的控制(缩放、旋转、俯视等)和定位功能,其中定位方面比较复杂一些。
lz也是自己一个人研究,未免有遗漏或者错误之处,希望大家指出,谢谢!




收藏
收藏0
分享
分享
点赞
点赞0
反对
反对0
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册
手机版