From 163ee916e5a868e6273641977bf413da2d233db8 Mon Sep 17 00:00:00 2001 From: Tobrun Van Nuland Date: Tue, 31 May 2016 17:02:49 +0200 Subject: [android] #4929 - rewrite MyLocationView with camera and transformation matrix --- .../mapboxsdk/maps/widgets/MyLocationView.java | 108 ++++++++++++--------- .../src/main/res/layout/mapview_internal.xml | 4 +- .../src/main/res/values/dimens.xml | 1 - 3 files changed, 63 insertions(+), 50 deletions(-) (limited to 'platform/android/MapboxGLAndroidSDK') 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 aed4e87c07..20513224f8 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 @@ -3,8 +3,10 @@ package com.mapbox.mapboxsdk.maps.widgets; import android.animation.ObjectAnimator; 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; import android.graphics.PorterDuff; @@ -22,6 +24,7 @@ import android.support.annotation.IntRange; import android.support.annotation.NonNull; import android.util.AttributeSet; import android.view.View; +import android.view.ViewGroup; import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.camera.CameraPosition; @@ -45,7 +48,6 @@ public class MyLocationView extends View { private MyLocationBehavior myLocationBehavior; private MapboxMap mapboxMap; private Projection projection; - private int maxSize; private int[] contentPadding = new int[4]; private Location location; @@ -57,8 +59,8 @@ public class MyLocationView extends View { private float gpsDirection; private float previousDirection; - private float accuracy = 0; - private Paint accuracyPaint = new Paint(); + private float accuracy; + private Paint accuracyPaint; private ValueAnimator locationChangeAnimator; private ValueAnimator accuracyAnimator; @@ -79,6 +81,11 @@ public class MyLocationView extends View { private int backgroundOffsetRight; private int backgroundOffsetBottom; + private Matrix matrix; + private Camera camera; + private PointF screenLocation; + private float tilt; + @MyLocationTracking.Mode private int myLocationTrackingMode; @@ -105,9 +112,20 @@ public class MyLocationView extends View { private void init(Context context) { setEnabled(false); + + // setup LayoutParams + ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT); + setLayoutParams(lp); + + matrix = new Matrix(); + camera = new Camera(); + camera.setLocation(0, 0, -1000); + accuracyPaint = new Paint(); + myLocationBehavior = new MyLocationBehaviorFactory().getBehavioralModel(MyLocationTracking.TRACKING_NONE); compassListener = new CompassListener(context); - maxSize = (int) context.getResources().getDimension(R.dimen.my_locationview_size); } public final void setForegroundDrawables(Drawable defaultDrawable, Drawable bearingDrawable) { @@ -151,7 +169,6 @@ public class MyLocationView extends View { backgroundOffsetTop = top; backgroundOffsetRight = right; backgroundOffsetBottom = bottom; - setShadowDrawableTint(backgroundTintColor); invalidateBounds(); @@ -187,19 +204,17 @@ public class MyLocationView extends View { int backgroundWidth = backgroundDrawable.getIntrinsicWidth(); int backgroundHeight = backgroundDrawable.getIntrinsicHeight(); - - int foregroundWidth = foregroundDrawable.getIntrinsicWidth(); - int foregroundHeight = foregroundDrawable.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); - int accuracyWidth = 2 * maxSize; - - backgroundBounds = new Rect(accuracyWidth - (backgroundWidth / 2) + horizontalOffset, accuracyWidth + verticalOffset - (backgroundWidth / 2), accuracyWidth + (backgroundWidth / 2) + horizontalOffset, accuracyWidth + (backgroundHeight / 2) + verticalOffset); - foregroundBounds = new Rect(accuracyWidth - (foregroundWidth / 2), accuracyWidth - (foregroundHeight / 2), accuracyWidth + (foregroundWidth / 2), accuracyWidth + (foregroundHeight / 2)); + int foregroundWidth = foregroundDrawable.getIntrinsicWidth(); + int foregroundHeight = foregroundDrawable.getIntrinsicHeight(); + foregroundBounds = new Rect(-foregroundWidth / 2, -foregroundHeight / 2, foregroundWidth / 2, foregroundHeight / 2); + foregroundDrawable.setBounds(foregroundBounds); - // invoke a new measure + // invoke a new draw invalidate(); } @@ -207,23 +222,44 @@ public class MyLocationView extends View { protected void onDraw(Canvas canvas) { super.onDraw(canvas); - if (location == null || foregroundBounds == null || backgroundBounds == null || accuracyAnimator == null) { + if (location == null || foregroundBounds == null || backgroundBounds == null || accuracyAnimator == null || screenLocation == null) { // Not ready yet return; } - // Draw circle float metersPerPixel = (float) projection.getMetersPerPixelAtLatitude(location.getLatitude()); - float accuracyPixels = (Float) accuracyAnimator.getAnimatedValue() / metersPerPixel; + float accuracyPixels = (Float) accuracyAnimator.getAnimatedValue() / metersPerPixel / 2; float maxRadius = getWidth() / 2; - canvas.drawCircle(foregroundBounds.centerX(), foregroundBounds.centerY(), accuracyPixels <= maxRadius ? accuracyPixels : maxRadius, accuracyPaint); + accuracyPixels = accuracyPixels <= maxRadius ? accuracyPixels : maxRadius; + + // put matrix in origin + matrix.reset(); + + // apply tilt to camera + camera.save(); + camera.rotate(tilt, 0, 0); + + // map camera matrix on our matrix + camera.getMatrix(matrix); - // Draw shadow + // put matrix at location of MyLocationView + matrix.postTranslate(screenLocation.x, screenLocation.y); + + // concat our matrix on canvas + canvas.concat(matrix); + + // restore orientation from camera + camera.restore(); + + // draw circle + canvas.drawCircle(0, 0, accuracyPixels, accuracyPaint); + + // draw shadow if (backgroundDrawable != null) { backgroundDrawable.draw(canvas); } - // Draw foreground + // draw foreground if (myBearingTrackingMode == MyBearingTracking.NONE) { if (foregroundDrawable != null) { foregroundDrawable.draw(canvas); @@ -233,27 +269,8 @@ public class MyLocationView extends View { } } - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - if (foregroundDrawable != null && foregroundBounds != null) { - foregroundDrawable.setBounds(foregroundBounds); - } - - if (foregroundBearingDrawable != null && foregroundBounds != null) { - foregroundBearingDrawable.setBounds(foregroundBounds); - } - - if (backgroundDrawable != null && backgroundBounds != null) { - backgroundDrawable.setBounds(backgroundBounds); - } - - setMeasuredDimension(4 * maxSize, 4 * maxSize); - } - public void setTilt(@FloatRange(from = 0, to = 60.0f) double tilt) { - setRotationX((float) tilt); + this.tilt = (float) tilt; } void updateOnNextFrame() { @@ -627,8 +644,9 @@ public class MyLocationView extends View { void invalidate() { int[] mapPadding = mapboxMap.getPadding(); UiSettings uiSettings = mapboxMap.getUiSettings(); - setX((uiSettings.getWidth() - getWidth() + mapPadding[0] - mapPadding[2]) / 2 + (contentPadding[0] - contentPadding[2]) / 2); - setY((uiSettings.getHeight() - getHeight() - mapPadding[3] + mapPadding[1]) / 2 + (contentPadding[1] - contentPadding[3]) / 2); + float x = (uiSettings.getWidth() - getWidth() + mapPadding[0] - mapPadding[2]) / 2 + (contentPadding[0] - contentPadding[2]) / 2; + float y = (uiSettings.getHeight() - getHeight() - mapPadding[3] + mapPadding[1]) / 2 + (contentPadding[1] - contentPadding[3]) / 2; + screenLocation = new PointF(x, y); MyLocationView.this.invalidate(); } } @@ -694,11 +712,7 @@ public class MyLocationView extends View { @Override void invalidate() { - PointF screenLocation = projection.toScreenLocation(latLng); - if (screenLocation != null) { - setX((screenLocation.x - getWidth() / 2)); - setY((screenLocation.y - getHeight() / 2)); - } + screenLocation = projection.toScreenLocation(latLng); MyLocationView.this.invalidate(); } } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapview_internal.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapview_internal.xml index 9799487f12..e944a5b4d1 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapview_internal.xml +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapview_internal.xml @@ -31,7 +31,7 @@ + android:layout_width="match_parent" + android:layout_height="match_parent" /> \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml index d6cca7090f..fd0f4b98e7 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml @@ -9,6 +9,5 @@ 10dp 16dp 76dp - 64dp 18dp -- cgit v1.2.1