diff options
author | Cameron Mace <cameron@mapbox.com> | 2016-12-16 16:19:15 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-16 16:19:15 -0500 |
commit | 20b958301eb208fe9ed0ae8edfb14b6f3741d8f2 (patch) | |
tree | 94ae0ce250cda159be13f9a21cc70c92d4908974 /platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java | |
parent | f95b4838ea816b9da0c151a953a1f98f97c79a39 (diff) | |
download | qtlocation-mapboxgl-20b958301eb208fe9ed0ae8edfb14b6f3741d8f2.tar.gz |
Adds checkstyle to CI (#7442)
* adds checkstyle to CI
* fixed gradlew path
* resolved testapp checkstyle violations
* added back mapboxMap variable for test
* checkstyle annotations
* checkstyle SDK round 1
* maps package checkstyle
* rest of SDK checkstyle
* checkstyle gesture library
* checkstyle test
* finished rest of test checkstyle
* resolved all checkstyle errors
* fixed class name
* removed old test file
* fixed camera postion test
* fixed native crash
Diffstat (limited to 'platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java')
-rw-r--r-- | platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java | 1245 |
1 files changed, 626 insertions, 619 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java index 677b59bea8..d34b0f693d 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java @@ -4,7 +4,6 @@ import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Camera; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PointF; @@ -44,745 +43,753 @@ import java.lang.ref.WeakReference; */ public class MyLocationView extends View { - private MyLocationBehavior myLocationBehavior; - private MapboxMap mapboxMap; + private MyLocationBehavior myLocationBehavior; + private MapboxMap mapboxMap; - private Projection projection; - private float[] projectedCoordinate = new float[2]; - private float projectedX; - private float projectedY; + private Projection projection; + private float[] projectedCoordinate = new float[2]; + private float projectedX; + private float projectedY; - private float contentPaddingX; - private float contentPaddingY; + private float contentPaddingX; + private float contentPaddingY; - private LatLng latLng; - private Location location; - private long locationUpdateTimestamp; - private float previousDirection; + private LatLng latLng; + private Location location; + private long locationUpdateTimestamp; + private float previousDirection; - private float accuracy; - private Paint accuracyPaint; + private float accuracy; + private Paint accuracyPaint; - private ValueAnimator locationChangeAnimator; - private ValueAnimator accuracyAnimator; - private ValueAnimator directionAnimator; + private ValueAnimator locationChangeAnimator; + private ValueAnimator accuracyAnimator; + private ValueAnimator directionAnimator; - private ValueAnimator.AnimatorUpdateListener invalidateSelfOnUpdateListener = - new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - invalidate(); - } - }; - - private Drawable foregroundDrawable; - private Drawable foregroundBearingDrawable; - private Drawable backgroundDrawable; - - private Rect foregroundBounds; - private Rect backgroundBounds; - - private int backgroundOffsetLeft; - private int backgroundOffsetTop; - private int backgroundOffsetRight; - private int backgroundOffsetBottom; - - private Matrix matrix; - private Camera camera; - private PointF screenLocation; + private ValueAnimator.AnimatorUpdateListener invalidateSelfOnUpdateListener = + new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + invalidate(); + } + }; - // camera vars - private double tilt; - private double bearing; - private float magneticHeading; + private Drawable foregroundDrawable; + private Drawable foregroundBearingDrawable; + private Drawable backgroundDrawable; - // Controls the compass update rate in milliseconds - private static final int COMPASS_UPDATE_RATE_MS = 500; + private Rect foregroundBounds; + private Rect backgroundBounds; - @MyLocationTracking.Mode - private int myLocationTrackingMode; + private int backgroundOffsetLeft; + private int backgroundOffsetTop; + private int backgroundOffsetRight; + private int backgroundOffsetBottom; - @MyBearingTracking.Mode - private int myBearingTrackingMode; + private Matrix matrix; + private Camera camera; + private PointF screenLocation; - private GpsLocationListener userLocationListener; - private CompassListener compassListener; + // camera vars + private double tilt; + private double bearing; + private float magneticHeading; - public MyLocationView(Context context) { - super(context); - init(context); - } + // Controls the compass update rate in milliseconds + private static final int COMPASS_UPDATE_RATE_MS = 500; - public MyLocationView(Context context, AttributeSet attrs) { - super(context, attrs); - init(context); - } + @MyLocationTracking.Mode + private int myLocationTrackingMode; - public MyLocationView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context); - } + @MyBearingTracking.Mode + private int myBearingTrackingMode; - private void init(Context context) { - if (isInEditMode()) { - return; - } + private GpsLocationListener userLocationListener; + private CompassListener compassListener; - setEnabled(false); + public MyLocationView(Context context) { + super(context); + init(context); + } - // setup LayoutParams - ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT); - setLayoutParams(lp); + public MyLocationView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context); + } - matrix = new Matrix(); - camera = new Camera(); - camera.setLocation(0, 0, -1000); - accuracyPaint = new Paint(); + public MyLocationView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context); + } - myLocationBehavior = new MyLocationBehaviorFactory().getBehavioralModel(MyLocationTracking.TRACKING_NONE); - compassListener = new CompassListener(context); + private void init(Context context) { + if (isInEditMode()) { + return; } - public final void setForegroundDrawables(Drawable defaultDrawable, Drawable bearingDrawable) { - if (defaultDrawable == null) { - return; - } + setEnabled(false); - if (bearingDrawable == null) { - // if user only provided one resource - // use same for bearing mode - bearingDrawable = defaultDrawable.getConstantState().newDrawable(); - } + // setup LayoutParams + ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT); + setLayoutParams(lp); - if (backgroundDrawable == null) { - // if the user didn't provide a background resource we will use the foreground resource instead, - // we need to create a new drawable to handle tinting correctly - backgroundDrawable = defaultDrawable.getConstantState().newDrawable(); - } + matrix = new Matrix(); + camera = new Camera(); + camera.setLocation(0, 0, -1000); + accuracyPaint = new Paint(); - if (defaultDrawable.getIntrinsicWidth() != bearingDrawable.getIntrinsicWidth() || defaultDrawable.getIntrinsicHeight() != bearingDrawable.getIntrinsicHeight()) { - throw new RuntimeException("The dimensions from location and bearing drawables should be match"); - } + myLocationBehavior = new MyLocationBehaviorFactory().getBehavioralModel(MyLocationTracking.TRACKING_NONE); + compassListener = new CompassListener(context); + } - foregroundDrawable = defaultDrawable; - foregroundBearingDrawable = bearingDrawable; + public final void setForegroundDrawables(Drawable defaultDrawable, Drawable bearingDrawable) { + if (defaultDrawable == null) { + return; + } - invalidateBounds(); + if (bearingDrawable == null) { + // if user only provided one resource + // use same for bearing mode + bearingDrawable = defaultDrawable.getConstantState().newDrawable(); } - public final void setForegroundDrawableTint(@ColorInt int color) { - if (foregroundDrawable != null) { - foregroundDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN); - } - if (foregroundBearingDrawable != null) { - foregroundBearingDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN); - } - invalidate(); + if (backgroundDrawable == null) { + // if the user didn't provide a background resource we will use the foreground resource instead, + // we need to create a new drawable to handle tinting correctly + backgroundDrawable = defaultDrawable.getConstantState().newDrawable(); } - public final void setShadowDrawable(Drawable drawable) { - setShadowDrawable(drawable, 0, 0, 0, 0); + if (defaultDrawable.getIntrinsicWidth() != bearingDrawable.getIntrinsicWidth() + || defaultDrawable.getIntrinsicHeight() != bearingDrawable.getIntrinsicHeight()) { + throw new RuntimeException("The dimensions from location and bearing drawables should be match"); } - public final void setShadowDrawable(Drawable drawable, int left, int top, int right, int bottom) { - if (drawable != null) { - backgroundDrawable = drawable; - } + foregroundDrawable = defaultDrawable; + foregroundBearingDrawable = bearingDrawable; - backgroundOffsetLeft = left; - backgroundOffsetTop = top; - backgroundOffsetRight = right; - backgroundOffsetBottom = bottom; + invalidateBounds(); + } - invalidateBounds(); + public final void setForegroundDrawableTint(@ColorInt int color) { + if (foregroundDrawable != null) { + foregroundDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN); } - - public final void setShadowDrawableTint(@ColorInt int color) { - if (backgroundDrawable == null) { - return; - } - backgroundDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN); - invalidate(); + if (foregroundBearingDrawable != null) { + foregroundBearingDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN); } + invalidate(); + } - public final void setAccuracyTint(@ColorInt int color) { - int alpha = accuracyPaint.getAlpha(); - accuracyPaint.setColor(color); - accuracyPaint.setAlpha(alpha); - invalidate(); - } + public final void setShadowDrawable(Drawable drawable) { + setShadowDrawable(drawable, 0, 0, 0, 0); + } - public final void setAccuracyAlpha(@IntRange(from = 0, to = 255) int alpha) { - accuracyPaint.setAlpha(alpha); - invalidate(); + public final void setShadowDrawable(Drawable drawable, int left, int top, int right, int bottom) { + if (drawable != null) { + backgroundDrawable = drawable; } - private void invalidateBounds() { - if (backgroundDrawable == null || foregroundDrawable == null || foregroundBearingDrawable == null) { - return; - } - - int backgroundWidth = backgroundDrawable.getIntrinsicWidth(); - int backgroundHeight = backgroundDrawable.getIntrinsicHeight(); - int horizontalOffset = backgroundOffsetLeft - backgroundOffsetRight; - int verticalOffset = backgroundOffsetTop - backgroundOffsetBottom; - backgroundBounds = new Rect(-backgroundWidth / 2 + horizontalOffset, -backgroundHeight / 2 + verticalOffset, backgroundWidth / 2 + horizontalOffset, backgroundHeight / 2 + verticalOffset); - backgroundDrawable.setBounds(backgroundBounds); + backgroundOffsetLeft = left; + backgroundOffsetTop = top; + backgroundOffsetRight = right; + backgroundOffsetBottom = bottom; - int foregroundWidth = foregroundDrawable.getIntrinsicWidth(); - int foregroundHeight = foregroundDrawable.getIntrinsicHeight(); - foregroundBounds = new Rect(-foregroundWidth / 2, -foregroundHeight / 2, foregroundWidth / 2, foregroundHeight / 2); - foregroundDrawable.setBounds(foregroundBounds); - foregroundBearingDrawable.setBounds(foregroundBounds); + invalidateBounds(); + } - // invoke a new draw - invalidate(); + public final void setShadowDrawableTint(@ColorInt int color) { + if (backgroundDrawable == null) { + return; } + backgroundDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN); + invalidate(); + } - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - if (location == null || foregroundBounds == null || backgroundBounds == null || accuracyAnimator == null || screenLocation == null) { - // Not ready yet - return; - } - - final PointF pointF = screenLocation; - float metersPerPixel = (float) projection.getMetersPerPixelAtLatitude(location.getLatitude()); - float accuracyPixels = (Float) accuracyAnimator.getAnimatedValue() / metersPerPixel / 2; - float maxRadius = getWidth() / 2; - accuracyPixels = accuracyPixels <= maxRadius ? accuracyPixels : maxRadius; - - // reset - matrix.reset(); - projectedCoordinate[0] = 0; - projectedCoordinate[1] = 0; + public final void setAccuracyTint(@ColorInt int color) { + int alpha = accuracyPaint.getAlpha(); + accuracyPaint.setColor(color); + accuracyPaint.setAlpha(alpha); + invalidate(); + } - // put camera in position - camera.save(); - camera.rotate((float) tilt, 0, 0); - camera.getMatrix(matrix); + public final void setAccuracyAlpha(@IntRange(from = 0, to = 255) int alpha) { + accuracyPaint.setAlpha(alpha); + invalidate(); + } - if (myBearingTrackingMode != MyBearingTracking.NONE && directionAnimator != null) { - matrix.preRotate((Float) directionAnimator.getAnimatedValue()); - } - - matrix.preTranslate(0, contentPaddingY); - matrix.postTranslate(pointF.x, pointF.y - contentPaddingY); - - // concat our matrix on canvas - canvas.concat(matrix); + private void invalidateBounds() { + if (backgroundDrawable == null || foregroundDrawable == null || foregroundBearingDrawable == null) { + return; + } - // calculate focal point - matrix.mapPoints(projectedCoordinate); - projectedX = pointF.x - projectedCoordinate[0]; - projectedY = pointF.y - projectedCoordinate[1]; + int backgroundWidth = backgroundDrawable.getIntrinsicWidth(); + int backgroundHeight = backgroundDrawable.getIntrinsicHeight(); + int horizontalOffset = backgroundOffsetLeft - backgroundOffsetRight; + int verticalOffset = backgroundOffsetTop - backgroundOffsetBottom; + backgroundBounds = new Rect(-backgroundWidth / 2 + horizontalOffset, + -backgroundHeight / 2 + verticalOffset, backgroundWidth / 2 + horizontalOffset, backgroundHeight / 2 + + verticalOffset); + backgroundDrawable.setBounds(backgroundBounds); - // restore orientation from camera - camera.restore(); + int foregroundWidth = foregroundDrawable.getIntrinsicWidth(); + int foregroundHeight = foregroundDrawable.getIntrinsicHeight(); + foregroundBounds = new Rect(-foregroundWidth / 2, -foregroundHeight / 2, foregroundWidth / 2, foregroundHeight / 2); + foregroundDrawable.setBounds(foregroundBounds); + foregroundBearingDrawable.setBounds(foregroundBounds); - // draw circle - canvas.drawCircle(0, 0, accuracyPixels, accuracyPaint); + // invoke a new draw + invalidate(); + } - // draw shadow - if (backgroundDrawable != null) { - backgroundDrawable.draw(canvas); - } + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); - // draw foreground - if (myBearingTrackingMode == MyBearingTracking.NONE) { - if (foregroundDrawable != null) { - foregroundDrawable.draw(canvas); - } - } else if (foregroundBearingDrawable != null && foregroundBounds != null) { - foregroundBearingDrawable.draw(canvas); - } + if (location == null || foregroundBounds == null || backgroundBounds == null || accuracyAnimator == null + || screenLocation == null) { + // Not ready yet + return; } - public void setTilt(@FloatRange(from = 0, to = 60.0f) double tilt) { - this.tilt = tilt; - if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { - mapboxMap.getUiSettings().setFocalPoint(new PointF(getCenterX(), getCenterY())); - } - } + final PointF pointF = screenLocation; + float metersPerPixel = (float) projection.getMetersPerPixelAtLatitude(location.getLatitude()); + float accuracyPixels = (Float) accuracyAnimator.getAnimatedValue() / metersPerPixel / 2; + float maxRadius = getWidth() / 2; + accuracyPixels = accuracyPixels <= maxRadius ? accuracyPixels : maxRadius; - public void setBearing(double bearing) { - this.bearing = bearing; - if (myLocationTrackingMode == MyLocationTracking.TRACKING_NONE) { - if (myBearingTrackingMode == MyBearingTracking.GPS) { - setCompass(location.getBearing() - bearing); - } else if (myBearingTrackingMode == MyBearingTracking.COMPASS) { - setCompass(magneticHeading - bearing); - } - } - } + // reset + matrix.reset(); + projectedCoordinate[0] = 0; + projectedCoordinate[1] = 0; - public void setCameraPosition(CameraPosition position) { - if (position != null) { - setTilt(position.tilt); - setBearing(position.bearing); - } - } + // put camera in position + camera.save(); + camera.rotate((float) tilt, 0, 0); + camera.getMatrix(matrix); - public void onStart() { - if (myBearingTrackingMode == MyBearingTracking.COMPASS) { - compassListener.onResume(); - } - if (isEnabled()) { - toggleGps(true); - } + if (myBearingTrackingMode != MyBearingTracking.NONE && directionAnimator != null) { + matrix.preRotate((Float) directionAnimator.getAnimatedValue()); } - public void onStop() { - compassListener.onPause(); - toggleGps(false); - } + matrix.preTranslate(0, contentPaddingY); + matrix.postTranslate(pointF.x, pointF.y - contentPaddingY); - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - // cleanup to prevent memory leaks - if (locationChangeAnimator != null) { - locationChangeAnimator.cancel(); - locationChangeAnimator = null; - } + // concat our matrix on canvas + canvas.concat(matrix); - if (accuracyAnimator != null) { - accuracyAnimator.cancel(); - accuracyAnimator = null; - } + // calculate focal point + matrix.mapPoints(projectedCoordinate); + projectedX = pointF.x - projectedCoordinate[0]; + projectedY = pointF.y - projectedCoordinate[1]; - if (directionAnimator != null) { - directionAnimator.cancel(); - directionAnimator = null; - } + // restore orientation from camera + camera.restore(); - if (userLocationListener != null) { - LocationServices services = LocationServices.getLocationServices(getContext()); - services.removeLocationListener(userLocationListener); - userLocationListener = null; - } - } + // draw circle + canvas.drawCircle(0, 0, accuracyPixels, accuracyPaint); - public void update() { - if (isEnabled()) { - myLocationBehavior.invalidate(); - } else { - setVisibility(View.INVISIBLE); - } + // draw shadow + if (backgroundDrawable != null) { + backgroundDrawable.draw(canvas); } - // TODO refactor MapboxMap out - public void setMapboxMap(MapboxMap mapboxMap) { - this.mapboxMap = mapboxMap; - this.projection = mapboxMap.getProjection(); - } + // draw foreground + if (myBearingTrackingMode == MyBearingTracking.NONE) { + if (foregroundDrawable != null) { + foregroundDrawable.draw(canvas); + } + } else if (foregroundBearingDrawable != null && foregroundBounds != null) { + foregroundBearingDrawable.draw(canvas); + } + } + + public void setTilt(@FloatRange(from = 0, to = 60.0f) double tilt) { + this.tilt = tilt; + if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { + mapboxMap.getUiSettings().setFocalPoint(new PointF(getCenterX(), getCenterY())); + } + } + + public void setBearing(double bearing) { + this.bearing = bearing; + if (myLocationTrackingMode == MyLocationTracking.TRACKING_NONE) { + if (myBearingTrackingMode == MyBearingTracking.GPS) { + setCompass(location.getBearing() - bearing); + } else if (myBearingTrackingMode == MyBearingTracking.COMPASS) { + setCompass(magneticHeading - bearing); + } + } + } + + public void setCameraPosition(CameraPosition position) { + if (position != null) { + setTilt(position.tilt); + setBearing(position.bearing); + } + } + + public void onStart() { + if (myBearingTrackingMode == MyBearingTracking.COMPASS) { + compassListener.onResume(); + } + if (isEnabled()) { + toggleGps(true); + } + } - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - setVisibility(enabled ? View.VISIBLE : View.INVISIBLE); - toggleGps(enabled); + public void onStop() { + compassListener.onPause(); + toggleGps(false); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + // cleanup to prevent memory leaks + if (locationChangeAnimator != null) { + locationChangeAnimator.cancel(); + locationChangeAnimator = null; } - @Override - protected Parcelable onSaveInstanceState() { - Bundle bundle = new Bundle(); - bundle.putParcelable("superState", super.onSaveInstanceState()); - bundle.putDouble("tilt", tilt); - return bundle; + if (accuracyAnimator != null) { + accuracyAnimator.cancel(); + accuracyAnimator = null; + } + + if (directionAnimator != null) { + directionAnimator.cancel(); + directionAnimator = null; + } + + if (userLocationListener != null) { + LocationServices services = LocationServices.getLocationServices(getContext()); + services.removeLocationListener(userLocationListener); + userLocationListener = null; + } + } + + public void update() { + if (isEnabled()) { + myLocationBehavior.invalidate(); + } else { + setVisibility(View.INVISIBLE); + } + } + + // TODO refactor MapboxMap out + public void setMapboxMap(MapboxMap mapboxMap) { + this.mapboxMap = mapboxMap; + this.projection = mapboxMap.getProjection(); + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + setVisibility(enabled ? View.VISIBLE : View.INVISIBLE); + toggleGps(enabled); + } + + @Override + protected Parcelable onSaveInstanceState() { + Bundle bundle = new Bundle(); + bundle.putParcelable("superState", super.onSaveInstanceState()); + bundle.putDouble("tilt", tilt); + return bundle; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + if (state instanceof Bundle) { + Bundle bundle = (Bundle) state; + tilt = bundle.getDouble("tilt"); + state = bundle.getParcelable("superState"); + } + super.onRestoreInstanceState(state); + } + + /** + * Enabled / Disable GPS location updates along with updating the UI + * + * @param enableGps true if GPS is to be enabled, false if GPS is to be disabled + */ + private void toggleGps(boolean enableGps) { + LocationServices locationServices = LocationServices.getLocationServices(getContext()); + if (enableGps) { + // Set an initial location if one available + Location lastLocation = locationServices.getLastLocation(); + + if (lastLocation != null) { + setLocation(lastLocation); + } + + if (userLocationListener == null) { + userLocationListener = new GpsLocationListener(this); + } + + locationServices.addLocationListener(userLocationListener); + } else { + // Disable location and user dot + location = null; + locationServices.removeLocationListener(userLocationListener); + } + + locationServices.toggleGPS(enableGps); + } + + public Location getLocation() { + return location; + } + + public void setLocation(Location location) { + if (location == null) { + this.location = null; + return; + } + + this.location = location; + myLocationBehavior.updateLatLng(location); + } + + public void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) { + this.myBearingTrackingMode = myBearingTrackingMode; + if (myBearingTrackingMode == MyBearingTracking.COMPASS) { + compassListener.onResume(); + } else { + compassListener.onPause(); + if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { + // always face north + setCompass(0); + } else { + myLocationBehavior.invalidate(); + } + } + invalidate(); + } + + public void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) { + MyLocationBehaviorFactory factory = new MyLocationBehaviorFactory(); + myLocationBehavior = factory.getBehavioralModel(myLocationTrackingMode); + + if (location != null) { + if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { + // center map directly + mapboxMap.easeCamera(CameraUpdateFactory.newLatLng(new LatLng(location)), 0, false /*linear interpolator*/, + false /*do not disable tracking*/, null); + } else { + // do not use interpolated location from tracking mode + latLng = null; + } + myLocationBehavior.updateLatLng(location); + } + + this.myLocationTrackingMode = myLocationTrackingMode; + invalidate(); + } + + @MyLocationTracking.Mode + public int getMyLocationTrackingMode() { + return myLocationTrackingMode; + } + + + @MyBearingTracking.Mode + public int getMyBearingTrackingMode() { + return myBearingTrackingMode; + } + + private void setCompass(double bearing) { + setCompass(bearing, 0 /* no animation */); + } + + private void setCompass(double bearing, long duration) { + float oldDir = previousDirection; + if (directionAnimator != null) { + oldDir = (Float) directionAnimator.getAnimatedValue(); + directionAnimator.end(); + directionAnimator = null; + } + + float newDir = (float) bearing; + float diff = oldDir - newDir; + if (diff > 180.0f) { + newDir += 360.0f; + } else if (diff < -180.0f) { + newDir -= 360.f; } + previousDirection = newDir; - @Override - public void onRestoreInstanceState(Parcelable state) { - if (state instanceof Bundle) { - Bundle bundle = (Bundle) state; - tilt = bundle.getDouble("tilt"); - state = bundle.getParcelable("superState"); - } - super.onRestoreInstanceState(state); - } + directionAnimator = ValueAnimator.ofFloat(oldDir, newDir); + directionAnimator.setDuration(duration); + directionAnimator.addUpdateListener(invalidateSelfOnUpdateListener); + directionAnimator.start(); + } - /** - * Enabled / Disable GPS location updates along with updating the UI - * - * @param enableGps true if GPS is to be enabled, false if GPS is to be disabled - */ - private void toggleGps(boolean enableGps) { - LocationServices locationServices = LocationServices.getLocationServices(getContext()); - if (enableGps) { - // Set an initial location if one available - Location lastLocation = locationServices.getLastLocation(); - - if (lastLocation != null) { - setLocation(lastLocation); - } + public float getCenterX() { + return (getX() + getMeasuredWidth()) / 2 + contentPaddingX - projectedX; + } - if (userLocationListener == null) { - userLocationListener = new GpsLocationListener(this); - } + public float getCenterY() { + return (getY() + getMeasuredHeight()) / 2 + contentPaddingY - projectedY; + } - locationServices.addLocationListener(userLocationListener); - } else { - // Disable location and user dot - location = null; - locationServices.removeLocationListener(userLocationListener); - } + public void setContentPadding(int[] padding) { + contentPaddingX = (padding[0] - padding[2]) / 2; + contentPaddingY = (padding[1] - padding[3]) / 2; + } + + private static class GpsLocationListener implements LocationListener { - locationServices.toggleGPS(enableGps); + private WeakReference<MyLocationView> userLocationView; + + GpsLocationListener(MyLocationView myLocationView) { + userLocationView = new WeakReference<>(myLocationView); } - public Location getLocation() { - return location; + /** + * Callback method for receiving location updates from LocationServices. + * + * @param location The new Location data + */ + @Override + public void onLocationChanged(Location location) { + MyLocationView locationView = userLocationView.get(); + if (locationView != null) { + locationView.setLocation(location); + } } + } - public void setLocation(Location location) { - if (location == null) { - this.location = null; - return; - } + private class CompassListener implements SensorEventListener { - this.location = location; - myLocationBehavior.updateLatLng(location); - } + private final SensorManager sensorManager; - public void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) { - this.myBearingTrackingMode = myBearingTrackingMode; - if (myBearingTrackingMode == MyBearingTracking.COMPASS) { - compassListener.onResume(); - } else { - compassListener.onPause(); - if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { - // always face north - setCompass(0); - } else { - myLocationBehavior.invalidate(); - } - } - invalidate(); - } + private Sensor rotationVectorSensor; + float[] matrix = new float[9]; + float[] orientation = new float[3]; - public void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) { - MyLocationBehaviorFactory factory = new MyLocationBehaviorFactory(); - myLocationBehavior = factory.getBehavioralModel(myLocationTrackingMode); + // Compass data + private long compassUpdateNextTimestamp = 0; - if (location != null) { - if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { - // center map directly - mapboxMap.easeCamera(CameraUpdateFactory.newLatLng(new LatLng(location)), 0, false /*linear interpolator*/, false /*do not disable tracking*/, null); - } else { - // do not use interpolated location from tracking mode - latLng = null; - } - myLocationBehavior.updateLatLng(location); - } + CompassListener(Context context) { + sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); + rotationVectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR); + } - this.myLocationTrackingMode = myLocationTrackingMode; - invalidate(); + public void onResume() { + sensorManager.registerListener(this, rotationVectorSensor, SensorManager.SENSOR_DELAY_GAME); } - @MyLocationTracking.Mode - public int getMyLocationTrackingMode() { - return myLocationTrackingMode; + public void onPause() { + sensorManager.unregisterListener(this, rotationVectorSensor); } + @Override + public void onSensorChanged(SensorEvent event) { - @MyBearingTracking.Mode - public int getMyBearingTrackingMode() { - return myBearingTrackingMode; - } + // check when the last time the compass was updated, return if too soon. + long currentTime = SystemClock.elapsedRealtime(); + if (currentTime < compassUpdateNextTimestamp) { + return; + } - private void setCompass(double bearing) { - setCompass(bearing, 0 /* no animation */); - } + if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) { - private void setCompass(double bearing, long duration) { - float oldDir = previousDirection; - if (directionAnimator != null) { - oldDir = (Float) directionAnimator.getAnimatedValue(); - directionAnimator.end(); - directionAnimator = null; - } + // calculate the rotation matrix + SensorManager.getRotationMatrixFromVector(matrix, event.values); + SensorManager.getOrientation(matrix, orientation); - float newDir = (float) bearing; - float diff = oldDir - newDir; - if (diff > 180.0f) { - newDir += 360.0f; - } else if (diff < -180.0f) { - newDir -= 360.f; + magneticHeading = (float) Math.toDegrees(SensorManager.getOrientation(matrix, orientation)[0]); + if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { + // Change the user location view orientation to reflect the device orientation + rotateCamera(magneticHeading); + setCompass(0, COMPASS_UPDATE_RATE_MS); + } else { + // Change compass direction + setCompass(magneticHeading - bearing, COMPASS_UPDATE_RATE_MS); } - previousDirection = newDir; - - directionAnimator = ValueAnimator.ofFloat(oldDir, newDir); - directionAnimator.setDuration(duration); - directionAnimator.addUpdateListener(invalidateSelfOnUpdateListener); - directionAnimator.start(); - } - public float getCenterX() { - return (getX() + getMeasuredWidth()) / 2 + contentPaddingX - projectedX; + compassUpdateNextTimestamp = currentTime + COMPASS_UPDATE_RATE_MS; + } } - public float getCenterY() { - return (getY() + getMeasuredHeight()) / 2 + contentPaddingY - projectedY; + private void rotateCamera(float rotation) { + CameraPosition.Builder builder = new CameraPosition.Builder(); + builder.bearing(rotation); + mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(builder.build()), COMPASS_UPDATE_RATE_MS, + false /*linear interpolator*/, false /*do not disable tracking*/, null); } - public void setContentPadding(int[] padding) { - contentPaddingX = (padding[0] - padding[2]) / 2; - contentPaddingY = (padding[1] - padding[3]) / 2; + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { } - private static class GpsLocationListener implements LocationListener { + } - private WeakReference<MyLocationView> userLocationView; + private class MarkerCoordinateAnimatorListener implements ValueAnimator.AnimatorUpdateListener { - GpsLocationListener(MyLocationView myLocationView) { - userLocationView = new WeakReference<>(myLocationView); - } + private MyLocationBehavior behavior; + private double fromLat; + private double fromLng; + private double toLat; + private double toLng; - /** - * Callback method for receiving location updates from LocationServices. - * - * @param location The new Location data - */ - @Override - public void onLocationChanged(Location location) { - MyLocationView locationView = userLocationView.get(); - if (locationView != null) { - locationView.setLocation(location); - } - } + private MarkerCoordinateAnimatorListener(MyLocationBehavior myLocationBehavior, LatLng from, LatLng to) { + behavior = myLocationBehavior; + fromLat = from.getLatitude(); + fromLng = from.getLongitude(); + toLat = to.getLatitude(); + toLng = to.getLongitude(); } - private class CompassListener implements SensorEventListener { - - private final SensorManager sensorManager; - - private Sensor rotationVectorSensor; - float[] matrix = new float[9]; - float[] orientation = new float[3]; - - // Compass data - private long compassUpdateNextTimestamp = 0; - - CompassListener(Context context) { - sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); - rotationVectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR); - } - - public void onResume() { - sensorManager.registerListener(this, rotationVectorSensor, SensorManager.SENSOR_DELAY_GAME); - } - - public void onPause() { - sensorManager.unregisterListener(this, rotationVectorSensor); - } - - @Override - public void onSensorChanged(SensorEvent event) { - - // check when the last time the compass was updated, return if too soon. - long currentTime = SystemClock.elapsedRealtime(); - if (currentTime < compassUpdateNextTimestamp) { - return; - } - - if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) { - - // calculate the rotation matrix - SensorManager.getRotationMatrixFromVector(matrix, event.values); - SensorManager.getOrientation(matrix, orientation); - - magneticHeading = (float) Math.toDegrees(SensorManager.getOrientation(matrix, orientation)[0]); - if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { - // Change the user location view orientation to reflect the device orientation - rotateCamera(magneticHeading); - setCompass(0, COMPASS_UPDATE_RATE_MS); - } else { - // Change compass direction - setCompass(magneticHeading - bearing, COMPASS_UPDATE_RATE_MS); - } - - compassUpdateNextTimestamp = currentTime + COMPASS_UPDATE_RATE_MS; - } - } - - private void rotateCamera(float rotation) { - CameraPosition.Builder builder = new CameraPosition.Builder(); - builder.bearing(rotation); - mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(builder.build()), COMPASS_UPDATE_RATE_MS, false /*linear interpolator*/, false /*do not disable tracking*/, null); - } + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float frac = animation.getAnimatedFraction(); + double latitude = fromLat + (toLat - fromLat) * frac; + double longitude = fromLng + (toLng - fromLng) * frac; + behavior.updateLatLng(latitude, longitude); + update(); + } + } - @Override - public void onAccuracyChanged(Sensor sensor, int accuracy) { - } + private class MyLocationBehaviorFactory { + MyLocationBehavior getBehavioralModel(@MyLocationTracking.Mode int mode) { + if (mode == MyLocationTracking.TRACKING_NONE) { + return new MyLocationShowBehavior(); + } else { + return new MyLocationTrackingBehavior(); + } } + } - private class MarkerCoordinateAnimatorListener implements ValueAnimator.AnimatorUpdateListener { + private abstract class MyLocationBehavior { - private MyLocationBehavior behavior; - private double fromLat; - private double fromLng; - private double toLat; - private double toLng; - - private MarkerCoordinateAnimatorListener(MyLocationBehavior myLocationBehavior, LatLng from, LatLng to) { - behavior = myLocationBehavior; - fromLat = from.getLatitude(); - fromLng = from.getLongitude(); - toLat = to.getLatitude(); - toLng = to.getLongitude(); - } + void updateLatLng(@NonNull Location newLocation) { + location = newLocation; + } - @Override - public void onAnimationUpdate(ValueAnimator animation) { - float frac = animation.getAnimatedFraction(); - double latitude = fromLat + (toLat - fromLat) * frac; - double longitude = fromLng + (toLng - fromLng) * frac; - behavior.updateLatLng(latitude, longitude); - update(); - } + void updateLatLng(double lat, double lon) { + if (latLng != null) { + latLng.setLatitude(lat); + latLng.setLongitude(lon); + } } - private class MyLocationBehaviorFactory { + void updateAccuracy(@NonNull Location location) { + if (accuracyAnimator != null && accuracyAnimator.isRunning()) { + // use current accuracy as a starting point + accuracy = (Float) accuracyAnimator.getAnimatedValue(); + accuracyAnimator.end(); + } - MyLocationBehavior getBehavioralModel(@MyLocationTracking.Mode int mode) { - if (mode == MyLocationTracking.TRACKING_NONE) { - return new MyLocationShowBehavior(); - } else { - return new MyLocationTrackingBehavior(); - } - } + accuracyAnimator = ValueAnimator.ofFloat(accuracy * 10, location.getAccuracy() * 10); + accuracyAnimator.setDuration(750); + accuracyAnimator.start(); + accuracy = location.getAccuracy(); } - private abstract class MyLocationBehavior { + abstract void invalidate(); + } - void updateLatLng(@NonNull Location newLocation) { - location = newLocation; - } + private class MyLocationTrackingBehavior extends MyLocationBehavior { - void updateLatLng(double lat, double lon) { - if (latLng != null) { - latLng.setLatitude(lat); - latLng.setLongitude(lon); - } - } + @Override + void updateLatLng(@NonNull Location location) { + super.updateLatLng(location); + if (latLng == null) { + // first location fix + latLng = new LatLng(location); + locationUpdateTimestamp = SystemClock.elapsedRealtime(); + } + + // updateLatLng timestamp + float previousUpdateTimeStamp = locationUpdateTimestamp; + locationUpdateTimestamp = SystemClock.elapsedRealtime(); + + // calculate animation duration + float animationDuration; + if (previousUpdateTimeStamp == 0) { + animationDuration = 0; + } else { + animationDuration = (locationUpdateTimestamp - previousUpdateTimeStamp) * 1.1f + /*make animation slightly longer*/; + } + + // calculate interpolated location + latLng = new LatLng(location); + CameraPosition.Builder builder = new CameraPosition.Builder().target(latLng); + + // add direction + if (myBearingTrackingMode == MyBearingTracking.GPS) { + if (location.hasBearing()) { + builder.bearing(location.getBearing()); + } + setCompass(0, COMPASS_UPDATE_RATE_MS); + } + + // accuracy + updateAccuracy(location); + + // ease to new camera position with a linear interpolator + mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(builder.build()), (int) animationDuration, + false /*linear interpolator*/, false /*do not disable tracking*/, null); + } - void updateAccuracy(@NonNull Location location) { - if (accuracyAnimator != null && accuracyAnimator.isRunning()) { - // use current accuracy as a starting point - accuracy = (Float) accuracyAnimator.getAnimatedValue(); - accuracyAnimator.end(); - } - - accuracyAnimator = ValueAnimator.ofFloat(accuracy * 10, location.getAccuracy() * 10); - accuracyAnimator.setDuration(750); - accuracyAnimator.start(); - accuracy = location.getAccuracy(); - } + @Override + void invalidate() { + int[] mapPadding = mapboxMap.getPadding(); + float x = (getWidth() + mapPadding[0] - mapPadding[2]) / 2 + contentPaddingX; + float y = (getHeight() - mapPadding[3] + mapPadding[1]) / 2 + contentPaddingY; + screenLocation = new PointF(x, y); + MyLocationView.this.invalidate(); + } + } - abstract void invalidate(); - } - - private class MyLocationTrackingBehavior extends MyLocationBehavior { - - @Override - void updateLatLng(@NonNull Location location) { - super.updateLatLng(location); - if (latLng == null) { - // first location fix - latLng = new LatLng(location); - locationUpdateTimestamp = SystemClock.elapsedRealtime(); - } - - // updateLatLng timestamp - float previousUpdateTimeStamp = locationUpdateTimestamp; - locationUpdateTimestamp = SystemClock.elapsedRealtime(); - - // calculate animation duration - float animationDuration; - if (previousUpdateTimeStamp == 0) { - animationDuration = 0; - } else { - animationDuration = (locationUpdateTimestamp - previousUpdateTimeStamp) * 1.1f /*make animation slightly longer*/; - } - - // calculate interpolated location - latLng = new LatLng(location); - CameraPosition.Builder builder = new CameraPosition.Builder().target(latLng); - - // add direction - if (myBearingTrackingMode == MyBearingTracking.GPS) { - if (location.hasBearing()) { - builder.bearing(location.getBearing()); - } - setCompass(0, COMPASS_UPDATE_RATE_MS); - } - - // accuracy - updateAccuracy(location); - - // ease to new camera position with a linear interpolator - mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(builder.build()), (int) animationDuration, false /*linear interpolator*/, false /*do not disable tracking*/, null); - } + private class MyLocationShowBehavior extends MyLocationBehavior { - @Override - void invalidate() { - int[] mapPadding = mapboxMap.getPadding(); - float x = (getWidth() + mapPadding[0] - mapPadding[2]) / 2 + contentPaddingX; - float y = (getHeight() - mapPadding[3] + mapPadding[1]) / 2 + contentPaddingY; - screenLocation = new PointF(x, y); - MyLocationView.this.invalidate(); - } + @Override + void updateLatLng(@NonNull final Location location) { + super.updateLatLng(location); + if (latLng == null) { + // first location update + latLng = new LatLng(location); + locationUpdateTimestamp = SystemClock.elapsedRealtime(); + } + + // update LatLng location + LatLng newLocation = new LatLng(location); + + // update LatLng accuracy + updateAccuracy(location); + + // calculate updateLatLng time + add some extra offset to improve animation + long previousUpdateTimeStamp = locationUpdateTimestamp; + locationUpdateTimestamp = SystemClock.elapsedRealtime(); + long locationUpdateDuration = (long) ((locationUpdateTimestamp - previousUpdateTimeStamp) * 1.2f); + + // animate changes + if (locationChangeAnimator != null) { + locationChangeAnimator.end(); + locationChangeAnimator = null; + } + + locationChangeAnimator = ValueAnimator.ofFloat(0.0f, 1.0f); + locationChangeAnimator.setDuration(locationUpdateDuration); + locationChangeAnimator.addUpdateListener(new MarkerCoordinateAnimatorListener(this, + latLng, newLocation + )); + locationChangeAnimator.start(); + latLng = newLocation; } - private class MyLocationShowBehavior extends MyLocationBehavior { - - @Override - void updateLatLng(@NonNull final Location location) { - super.updateLatLng(location); - if (latLng == null) { - // first location update - latLng = new LatLng(location); - locationUpdateTimestamp = SystemClock.elapsedRealtime(); - } - - // update LatLng location - LatLng newLocation = new LatLng(location); - - // update LatLng accuracy - updateAccuracy(location); - - // calculate updateLatLng time + add some extra offset to improve animation - long previousUpdateTimeStamp = locationUpdateTimestamp; - locationUpdateTimestamp = SystemClock.elapsedRealtime(); - long locationUpdateDuration = (long) ((locationUpdateTimestamp - previousUpdateTimeStamp) * 1.2f); - - // animate changes - if (locationChangeAnimator != null) { - locationChangeAnimator.end(); - locationChangeAnimator = null; - } - - locationChangeAnimator = ValueAnimator.ofFloat(0.0f, 1.0f); - locationChangeAnimator.setDuration(locationUpdateDuration); - locationChangeAnimator.addUpdateListener(new MarkerCoordinateAnimatorListener(this, - latLng, newLocation - )); - locationChangeAnimator.start(); - latLng = newLocation; - } - - @Override - void invalidate() { - if (latLng != null) { - screenLocation = projection.toScreenLocation(latLng); - } - MyLocationView.this.invalidate(); - } + @Override + void invalidate() { + if (latLng != null) { + screenLocation = projection.toScreenLocation(latLng); + } + MyLocationView.this.invalidate(); } + } } |