该功能的实现依赖于手机中的传感器元件如陀螺仪、加速度计等,具体开发详见android的官方开发文档:
传感器概览 | Android 开发者 | Android Developershttps://developer.android.com/guide/topics/sensors/sensors_overview?hl=zh-cn要自定义一个传感器监听器类实现该功能,套路与实现定位功能类似,但是网上关于定位图标随手机方向转动的文章并不多,且大多割裂了与定位功能之间的联系。
首先自定义一个传感器监听器类:
//自定义传感器监听器类
public class MyOrientationListener implements SensorEventListener{
private SensorManager sensorManager;
//注册传感器监听器方法
public void registerSensorListener() {
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
SensorManager.SENSOR_DELAY_UI);
}
// 关闭传感器监听器的方法
public void unregisterSensorListener() {
sensorManager.unregisterListener(this);
}
// 监听传感器变化事件,当传感器数值发生变化时,该方法被调用
public void onSensorChanged(SensorEvent sensorEvent) {
// 读取传感器数值中的 x 轴方向的值
double x = sensorEvent.values[SensorManager.DATA_X];
// 判断当前 x 轴方向的值与上一次记录的值之间的差值是否超过了 1.0,如果超过了 1.0,更新当前方向为新的 x 轴方向的值。
if (Math.abs(x - lastX) > 1.0) {
mCurrentDirection = (float) x;
// 构造定位图层数据
MyLocationData myLocationData = new MyLocationData.Builder()
.accuracy(mCurrentAccracy)
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(mCurrentDirection)
.latitude(mCurrentLantitude)
.longitude(mCurrentLongtitude).build();
// 设置定位图层数据
baiduMap.setMyLocationData(myLocationData);
}
// 将当前 x 轴方向的值记录为上一次的值,用于下一次比较
lastX = x;
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// 传感器精度变化时的回调方法
}
}
SensorEventListener
是一个接口,它用于监听传感器事件的回调。当与传感器相关的事件发生时,系统会调用 SensorEventListener
的方法来通知你。
在这个类中要自己实现注册监听器和注销监听器的方法,这两种方法的实现官方文档中都有,可以直接用:
定位图标指示方向 | 百度地图API SDK (baidu.com)https://lbsyun.baidu.com/index.php?title=%E5%AE%9A%E4%BD%8D%E5%9B%BE%E6%A0%87%E6%8C%87%E7%A4%BA%E6%96%B9%E5%90%91关键是onSensorChanged这个方法,是该功能实现的核心,在该方法中定义了处理传感器信息的逻辑,如何确定方向。
在构造定位图层数据时,经纬度和精确度都可以从定位功能的监听器中直接取:
定位功能实现详见android开发调用百度地图api实现加载地图和定位-CSDN博客
//通过继承抽象类BDAbstractListener并重写其onReceieveLocation方法来获取定位数据,并将其传给MapView。
public class MyLocationListener extends BDAbstractLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
int locType = location.getLocType();
Log.d("定位结果错误码", String.valueOf(locType));
//mapView 销毁后不再处理新接收的位置
if (location == null || mMapView == null) { //判断 location 和 mMapView 是否为空来确保在地图视图销毁后不再处理新接收的位置
return;
}
mCurrentLongtitude = location.getLongitude();
mCurrentLantitude = location.getLatitude();
mCurrentAccracy = location.getRadius();
MyLocationData locData = new MyLocationData.Builder() //通过 Builder 模式,设置位置的精度、方向、纬度和经度等属性。
.accuracy(location.getRadius())
// 从传感器拿到方向信息
.direction(mCurrentDirection)
.latitude(location.getLatitude())
.longitude(location.getLongitude())
.build();
baiduMap.setMyLocationData(locData); //将新的位置信息更新到地图上,以显示当前设备的位置
其中mCurrentLongtitude、mCurrentLantitude、mCurrentAccracy这三个变量在MainActivity的onCreate方法之前定义,在定位监听器中获取经纬度和精确度值然后在传感器监听器中使用。
但是关键在方向的获取:
博主最开始编写完该功能之后,发现一个现象:图标箭头可以随着手机的转动而转动,但是每当转动一个角度之后都会弹回最开始的方向,并不能最终指向正确方向,经过研究,博主发现是因为传感器获取到的方向信息并没有持续传递给定位功能,导致每次手机停止转动之后,定位监听器类拿到的方向信息都不是手机的最新方向。
所以当每次传感器类中计算完方向之后都要把方向传递给定位功能:
//通过 Builder 模式,设置位置的精度、方向、纬度和经度等属性。
MyLocationData locData = new MyLocationData.Builder()
.accuracy(location.getRadius())
// 从传感器拿到方向信息
.direction(mCurrentDirection)
.latitude(location.getLatitude())
.longitude(location.getLongitude())
.build();
最后还要打开显示方向信息:
这部分代码放在onCreate()中就可以
// 创建 MyLocationConfiguration 对象并设置相关属性,enableDirection=true则允许显示方向
MyLocationConfiguration config = new MyLocationConfiguration(
MyLocationConfiguration.LocationMode.FOLLOWING, // 定位模式为跟随态 true, // 显示方向信息
null,
0xAAec2d7a, // 填充颜色
0xAA2376b7 // 描边颜色
);
baiduMap.setMyLocationConfiguration(config);
注册监听器和注销监听器的方法不要忘记调用:
@Override
protected void onResume() {
super.onResume();
//开始传感器监听
myOrientationListener.registerSensorListener();
//在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理
mMapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
//终止传感器监听
myOrientationListener.unregisterSensorListener();
//在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理
mMapView.onPause();
}