[android] #4929 - rewrite MyLocationView with camera and transformation matrix
This commit is contained in:
committed by
Brad Leege
parent
c7fb8890fe
commit
163ee916e5
@@ -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 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 foregroundWidth = foregroundDrawable.getIntrinsicWidth();
|
||||
int foregroundHeight = foregroundDrawable.getIntrinsicHeight();
|
||||
foregroundBounds = new Rect(-foregroundWidth / 2, -foregroundHeight / 2, foregroundWidth / 2, foregroundHeight / 2);
|
||||
foregroundDrawable.setBounds(foregroundBounds);
|
||||
|
||||
int horizontalOffset = backgroundOffsetLeft - backgroundOffsetRight;
|
||||
int verticalOffset = backgroundOffsetTop - backgroundOffsetBottom;
|
||||
|
||||
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));
|
||||
|
||||
// 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;
|
||||
|
||||
// Draw shadow
|
||||
// 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);
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user