[Android] Refactored Compass in separate View class

[Android] Merged MapView master
This commit is contained in:
Tobrun
2015-09-30 17:06:02 +02:00
parent ab6090fccb
commit 135ce4b67e
2 changed files with 174 additions and 88 deletions

View File

@@ -64,6 +64,7 @@ import com.mapbox.mapboxgl.annotations.PolylineOptions;
import com.mapbox.mapboxgl.geometry.BoundingBox;
import com.mapbox.mapboxgl.geometry.LatLng;
import com.mapbox.mapboxgl.geometry.LatLngZoom;
import com.mapbox.mapboxgl.views.widgets.CompassView;
import com.mapzen.android.lost.api.LocationListener;
import com.mapzen.android.lost.api.LocationRequest;
import com.mapzen.android.lost.api.LocationServices;
@@ -90,7 +91,7 @@ import java.util.List;
* <p><b>Warning:</b> Please note that you are responsible for getting permission to use the map data,
* and for ensuring your use adheres to the relevant terms of use.</p>
*/
public class MapView extends FrameLayout implements LocationListener {
public class MapView extends FrameLayout implements LocationListener, CompassView.CompassDelegate {
//
// Static members
@@ -181,18 +182,7 @@ public class MapView extends FrameLayout implements LocationListener {
private Location mGpsLocation;
// Used for the compass
private ImageView mCompassView;
private SensorManager mSensorManager;
private Sensor mSensorAccelerometer;
private Sensor mSensorMagneticField;
private CompassListener mCompassListener;
private float[] mValuesAccelerometer = new float[3];
private float[] mValuesMagneticField = new float[3];
private float[] mMatrixR = new float[9];
private float[] mMatrixI = new float[9];
private float[] mMatrixValues = new float[3];
private float mCompassBearing;
private boolean mCompassValid = false;
private CompassView mCompassView;
// Used for displaying annotation markers
// Every annotation that has been added to the map
@@ -223,7 +213,6 @@ public class MapView extends FrameLayout implements LocationListener {
private boolean mRotateEnabled = true;
private String mStyleUrl;
private boolean mIsMyLocationEnabled = false;
private boolean mIsCompassEnabled = true;
//
// Enums
@@ -473,22 +462,10 @@ public class MapView extends FrameLayout implements LocationListener {
addView(mGpsMarker);
// Setup compass
mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
mSensorAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorMagneticField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
mCompassListener = new CompassListener();
// Setup compass UI
mCompassView = new ImageView(mContext);
mCompassView.setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.compass));
mCompassView.setContentDescription(getResources().getString(R.string.compassContentDescription));
LayoutParams lp = new FrameLayout.LayoutParams(
(int) (48 * mScreenDensity),
(int) (48 * mScreenDensity));
mCompassView.setLayoutParams(lp);
mCompassView = new CompassView(mContext);
mCompassView.setVisibility(View.INVISIBLE);
mCompassView.setOnClickListener(new CompassView.CompassClickListener(this));
addView(mCompassView);
mCompassView.setOnClickListener(new CompassOnClickListener());
// Setup Mapbox logo
mLogoView = new ImageView(mContext);
@@ -2141,16 +2118,14 @@ public class MapView extends FrameLayout implements LocationListener {
mLocationClient.connect();
updateLocation(LocationServices.FusedLocationApi.getLastLocation());
LocationServices.FusedLocationApi.requestLocationUpdates(mLocationRequest, this);
//mSensorManager.registerListener(mCompassListener, mSensorAccelerometer, SensorManager.SENSOR_DELAY_UI);
//mSensorManager.registerListener(mCompassListener, mSensorMagneticField, SensorManager.SENSOR_DELAY_UI);
mCompassView.registerListeners(this);
}
} else {
if (mLocationClient.isConnected()) {
mCompassView.unRegisterListeners();
LocationServices.FusedLocationApi.removeLocationUpdates(this);
mLocationClient.disconnect();
mGpsLocation = null;
//mSensorManager.unregisterListener(mCompassListener, mSensorAccelerometer);
//mSensorManager.unregisterListener(mCompassListener, mSensorMagneticField);
}
}
@@ -2220,7 +2195,7 @@ public class MapView extends FrameLayout implements LocationListener {
* @return true if the compass is enabled; false if the compass is disabled.
*/
public boolean isCompassEnabled() {
return mIsCompassEnabled;
return mCompassView.isEnabled();
}
/**
@@ -2235,7 +2210,7 @@ public class MapView extends FrameLayout implements LocationListener {
* @param compassEnabled true to enable the compass; false to disable the compass.
*/
public void setCompassEnabled(boolean compassEnabled) {
this.mIsCompassEnabled = compassEnabled;
mCompassView.setEnabled(compassEnabled);
onInvalidate();
}
@@ -2247,60 +2222,6 @@ public class MapView extends FrameLayout implements LocationListener {
setWidgetMargins(mCompassView, left, top, right, bottom);
}
// This class handles sensor updates to calculate compass bearing
private class CompassListener implements SensorEventListener {
@Override
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values, 0, mValuesAccelerometer, 0, 3);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
System.arraycopy(event.values, 0, mValuesMagneticField, 0, 3);
break;
}
boolean valid = SensorManager.getRotationMatrix(mMatrixR, mMatrixI,
mValuesAccelerometer,
mValuesMagneticField);
if (valid) {
SensorManager.getOrientation(mMatrixR, mMatrixValues);
//mAzimuthRadians.putValue(mMatrixValues[0]);
//mAzimuth = Math.toDegrees(mAzimuthRadians.getAverage());
Location mGpsLocation = getMyLocation();
if (mGpsLocation != null) {
GeomagneticField geomagneticField = new GeomagneticField(
(float) mGpsLocation.getLatitude(),
(float) mGpsLocation.getLongitude(),
(float) mGpsLocation.getAltitude(),
System.currentTimeMillis());
mCompassBearing = (float) Math.toDegrees(mMatrixValues[0]) + geomagneticField.getDeclination();
mCompassValid = true;
}
}
onInvalidate();
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO: ignore unreliable stuff
}
}
// Called when someone presses the compass
private class CompassOnClickListener implements View.OnClickListener {
@Override
public void onClick(View view) {
resetNorth();
}
}
// Rotates an ImageView - does not work if the ImageView has padding, use margins
private void rotateImageView(ImageView imageView, float angle) {
Matrix matrix = new Matrix();
@@ -2320,6 +2241,11 @@ public class MapView extends FrameLayout implements LocationListener {
}
}
@Override
public Location getLocation() {
return mGpsLocation;
}
//
// Logo
//

View File

@@ -0,0 +1,160 @@
package com.mapbox.mapboxgl.views.widgets;
import android.content.Context;
import android.hardware.GeomagneticField;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.mapbox.mapboxgl.views.MapView;
import com.mapbox.mapboxgl.views.R;
import java.lang.ref.WeakReference;
public class CompassView extends ImageView implements SensorEventListener {
private CompassDelegate mCompassDelegate;
// Sensor model
private SensorManager mSensorManager;
private Sensor mSensorAccelerometer;
private Sensor mSensorMagneticField;
// Sensor data
private boolean mSensorValid;
private float[] mValuesAccelerometer = new float[3];
private float[] mValuesMagneticField = new float[3];
private float[] mMatrixR = new float[9];
private float[] mMatrixI = new float[9];
private float[] mMatrixValues = new float[3];
// Location data
private GeomagneticField mGeomagneticField;
private Location mGpsLocation;
// Compass date
private float mCompassBearing;
private boolean mCompassValid;
public CompassView(Context context) {
super(context);
initialize(context);
}
public CompassView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context);
}
public CompassView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize(context);
}
private void initialize(Context context) {
// Sensor initialisation
mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
mSensorAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorMagneticField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
// View configuration
setImageDrawable(ContextCompat.getDrawable(getContext(), R.drawable.compass));
setContentDescription(getResources().getString(R.string.compassContentDescription));
// Layout params
float mScreenDensity = context.getResources().getDisplayMetrics().density;
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams((int) (48 * mScreenDensity), (int) (48 * mScreenDensity));
setLayoutParams(lp);
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
}
public boolean isValid() {
return mCompassValid;
}
public float getBearing() {
return mCompassBearing;
}
public void registerListeners(CompassDelegate compassDelegate) {
mSensorManager.registerListener(this, mSensorAccelerometer, SensorManager.SENSOR_DELAY_UI);
mSensorManager.registerListener(this, mSensorMagneticField, SensorManager.SENSOR_DELAY_UI);
mCompassDelegate = compassDelegate;
}
public void unRegisterListeners() {
mCompassDelegate = null;
mSensorManager.unregisterListener(this, mSensorMagneticField);
mSensorManager.unregisterListener(this, mSensorAccelerometer);
}
@Override
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values, 0, mValuesAccelerometer, 0, 3);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
System.arraycopy(event.values, 0, mValuesMagneticField, 0, 3);
break;
}
mSensorValid = SensorManager.getRotationMatrix(mMatrixR, mMatrixI,
mValuesAccelerometer,
mValuesMagneticField);
if (mSensorValid && mCompassDelegate != null) {
SensorManager.getOrientation(mMatrixR, mMatrixValues);
mGpsLocation = mCompassDelegate.getLocation();
if (mGpsLocation != null) {
mGeomagneticField = new GeomagneticField(
(float) mGpsLocation.getLatitude(),
(float) mGpsLocation.getLongitude(),
(float) mGpsLocation.getAltitude(),
System.currentTimeMillis());
mCompassBearing = (float) Math.toDegrees(mMatrixValues[0]) + mGeomagneticField.getDeclination();
mCompassValid = true;
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO: ignore unreliable stuff
}
public interface CompassDelegate {
Location getLocation();
}
public static class CompassClickListener implements View.OnClickListener {
private WeakReference<MapView> mMapView;
public CompassClickListener(final MapView mapView) {
mMapView = new WeakReference<>(mapView);
}
@Override
public void onClick(View v) {
final MapView mapView = mMapView.get();
if (mapView != null) {
mapView.resetNorth();
}
}
}
}