[Android] Refactored Compass in separate View class
[Android] Merged MapView master
This commit is contained in:
@@ -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
|
||||
//
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user