com.mapbox.mapboxsdk.maps.widgets.UserLocationView Maven / Gradle / Ivy
package com.mapbox.mapboxsdk.maps.widgets;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.os.Build;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.constants.MyBearingTracking;
import com.mapbox.mapboxsdk.constants.MyLocationTracking;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.location.LocationListener;
import com.mapbox.mapboxsdk.location.LocationServices;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.Projection;
import java.lang.ref.WeakReference;
/**
* UI element overlaid on a map to show the user's location.
*/
public final class UserLocationView extends View {
private MapboxMap mMapboxMap;
private Projection mProjection;
private boolean mShowMarker;
private boolean mShowDirection;
private boolean mShowAccuracy;
private boolean mStaleMarker;
private PointF mMarkerScreenPoint;
private Matrix mMarkerScreenMatrix;
private Paint mAccuracyPaintFill;
private Paint mAccuracyPaintStroke;
private Path mAccuracyPath;
private RectF mAccuracyBounds;
private Drawable mUserLocationDrawable;
private RectF mUserLocationDrawableBoundsF;
private Rect mUserLocationDrawableBounds;
private Drawable mUserLocationBearingDrawable;
private RectF mUserLocationBearingDrawableBoundsF;
private Rect mUserLocationBearingDrawableBounds;
private Drawable mUserLocationStaleDrawable;
private RectF mUserLocationStaleDrawableBoundsF;
private Rect mUserLocationStaleDrawableBounds;
private Rect mDirtyRect;
private RectF mDirtyRectF;
private LatLng mMarkerCoordinate;
private ValueAnimator mMarkerCoordinateAnimator;
private float mGpsMarkerDirection;
private float mCompassMarkerDirection;
private ObjectAnimator mMarkerDirectionAnimator;
private float mMarkerAccuracy;
private ObjectAnimator mMarkerAccuracyAnimator;
private LatLng mCurrentMapViewCoordinate;
private double mCurrentBearing;
private boolean mPaused = false;
private Location mUserLocation;
private UserLocationListener mUserLocationListener;
private MapboxMap.OnMyLocationChangeListener mOnMyLocationChangeListener;
@MyLocationTracking.Mode
private int mMyLocationTrackingMode;
@MyBearingTracking.Mode
private int mMyBearingTrackingMode;
// Compass data
private MyBearingListener mBearingChangeListener;
public UserLocationView(Context context) {
super(context);
initialize(context);
}
public UserLocationView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context);
}
public UserLocationView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize(context);
}
private void initialize(Context context) {
// View configuration
setEnabled(false);
setWillNotDraw(false);
// Layout params
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
setLayoutParams(lp);
// Setup sensors
mBearingChangeListener = new MyBearingListener(context);
// Setup the custom paint
Resources resources = context.getResources();
int accuracyColor = ContextCompat.getColor(context,R.color.my_location_ring);
float density = resources.getDisplayMetrics().density;
mMarkerCoordinate = new LatLng(0.0, 0.0);
mMarkerScreenPoint = new PointF();
mMarkerScreenMatrix = new Matrix();
mAccuracyPaintFill = new Paint();
mAccuracyPaintFill.setAntiAlias(true);
mAccuracyPaintFill.setStyle(Paint.Style.FILL);
mAccuracyPaintFill.setColor(accuracyColor);
mAccuracyPaintFill.setAlpha((int) (255 * 0.25f));
mAccuracyPaintStroke = new Paint();
mAccuracyPaintStroke.setAntiAlias(true);
mAccuracyPaintStroke.setStyle(Paint.Style.STROKE);
mAccuracyPaintStroke.setStrokeWidth(0.5f * density);
mAccuracyPaintStroke.setColor(accuracyColor);
mAccuracyPaintStroke.setAlpha((int) (255 * 0.5f));
mAccuracyPath = new Path();
mAccuracyBounds = new RectF();
mUserLocationDrawable = ContextCompat.getDrawable(getContext(), R.drawable.my_location);
mUserLocationDrawableBounds = new Rect(
-mUserLocationDrawable.getIntrinsicWidth() / 2,
-mUserLocationDrawable.getIntrinsicHeight() / 2,
mUserLocationDrawable.getIntrinsicWidth() / 2,
mUserLocationDrawable.getIntrinsicHeight() / 2);
mUserLocationDrawableBoundsF = new RectF(
-mUserLocationDrawable.getIntrinsicWidth() / 2,
-mUserLocationDrawable.getIntrinsicHeight() / 2,
mUserLocationDrawable.getIntrinsicWidth() / 2,
mUserLocationDrawable.getIntrinsicHeight() / 2);
mUserLocationDrawable.setBounds(mUserLocationDrawableBounds);
mUserLocationBearingDrawable = ContextCompat.getDrawable(getContext(), R.drawable.my_location_bearing);
mUserLocationBearingDrawableBounds = new Rect(
-mUserLocationBearingDrawable.getIntrinsicWidth() / 2,
-mUserLocationBearingDrawable.getIntrinsicHeight() / 2,
mUserLocationBearingDrawable.getIntrinsicWidth() / 2,
mUserLocationBearingDrawable.getIntrinsicHeight() / 2);
mUserLocationBearingDrawableBoundsF = new RectF(
-mUserLocationBearingDrawable.getIntrinsicWidth() / 2,
-mUserLocationBearingDrawable.getIntrinsicHeight() / 2,
mUserLocationBearingDrawable.getIntrinsicWidth() / 2,
mUserLocationBearingDrawable.getIntrinsicHeight() / 2);
mUserLocationBearingDrawable.setBounds(mUserLocationBearingDrawableBounds);
mUserLocationStaleDrawable = ContextCompat.getDrawable(getContext(), R.drawable.my_location_stale);
mUserLocationStaleDrawableBounds = new Rect(
-mUserLocationStaleDrawable.getIntrinsicWidth() / 2,
-mUserLocationStaleDrawable.getIntrinsicHeight() / 2,
mUserLocationStaleDrawable.getIntrinsicWidth() / 2,
mUserLocationStaleDrawable.getIntrinsicHeight() / 2);
mUserLocationStaleDrawableBoundsF = new RectF(
-mUserLocationStaleDrawable.getIntrinsicWidth() / 2,
-mUserLocationStaleDrawable.getIntrinsicHeight() / 2,
mUserLocationStaleDrawable.getIntrinsicWidth() / 2,
mUserLocationStaleDrawable.getIntrinsicHeight() / 2);
mUserLocationStaleDrawable.setBounds(mUserLocationStaleDrawableBounds);
}
public void setMapboxMap(MapboxMap mapboxMap) {
mMapboxMap = mapboxMap;
mProjection = mapboxMap.getProjection();
}
public void onStart() {
if (mMyBearingTrackingMode == MyBearingTracking.COMPASS) {
mBearingChangeListener.onStart(getContext());
}
}
public void onStop() {
mBearingChangeListener.onStop();
cancelAnimations();
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (!mShowMarker) {
return;
}
canvas.concat(mMarkerScreenMatrix);
Drawable dotDrawable = mShowDirection ? mUserLocationBearingDrawable : mUserLocationDrawable;
dotDrawable = mStaleMarker ? mUserLocationStaleDrawable : dotDrawable;
// IMPORTANT also update in update()
RectF dotBounds = mShowDirection ? mUserLocationBearingDrawableBoundsF : mUserLocationDrawableBoundsF;
dotBounds = mStaleMarker ? mUserLocationStaleDrawableBoundsF : dotBounds;
boolean willDraw = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN || !canvas.isHardwareAccelerated()) {
willDraw = mShowAccuracy && !mStaleMarker && !canvas.quickReject(mAccuracyPath, Canvas.EdgeType.AA);
}
willDraw |= !canvas.quickReject(dotBounds, Canvas.EdgeType.AA);
if (willDraw) {
if (mShowAccuracy && !mStaleMarker) {
canvas.drawPath(mAccuracyPath, mAccuracyPaintFill);
canvas.drawPath(mAccuracyPath, mAccuracyPaintStroke);
}
dotDrawable.draw(canvas);
}
}
public void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) {
mMyLocationTrackingMode = myLocationTrackingMode;
if (myLocationTrackingMode != MyLocationTracking.TRACKING_NONE && mUserLocation != null) {
// center map directly if we have a location fix
mMarkerCoordinate = new LatLng(mUserLocation.getLatitude(), mUserLocation.getLongitude());
mMapboxMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(mUserLocation)));
// center view directly
mMarkerScreenMatrix.reset();
mMarkerScreenPoint = getMarkerScreenPoint();
mMarkerScreenMatrix.setTranslate(mMarkerScreenPoint.x, mMarkerScreenPoint.y);
}
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
toggleGps(enabled);
}
public void update() {
if (isEnabled() && mShowMarker) {
setVisibility(View.VISIBLE);
mStaleMarker = isStale(mUserLocation);
// compute new marker position
// TODO add JNI method that takes existing pointf
if (mMyLocationTrackingMode == MyLocationTracking.TRACKING_NONE) {
mMarkerScreenPoint = getMarkerScreenPoint();
mMarkerScreenMatrix.reset();
mMarkerScreenMatrix.setTranslate(
mMarkerScreenPoint.x,
mMarkerScreenPoint.y);
} else if (mMyLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
double bearing;
if (mShowDirection) {
bearing = mMyBearingTrackingMode == MyBearingTracking.COMPASS ? mBearingChangeListener.getCompassBearing() : mUserLocation.getBearing();
} else {
bearing = mMapboxMap.getCameraPosition().bearing;
}
if (mCurrentMapViewCoordinate == null) {
mCurrentMapViewCoordinate = mMapboxMap.getCameraPosition().target;
}
// only update if there is an actual change
if ((!mCurrentMapViewCoordinate.equals(mMarkerCoordinate)) || (!(mCurrentBearing == bearing))) {
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(mMarkerCoordinate)
.bearing(bearing)
.build();
mMapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 300, null);
mMarkerScreenMatrix.reset();
mMarkerScreenPoint = getMarkerScreenPoint();
mMarkerScreenMatrix.setTranslate(mMarkerScreenPoint.x, mMarkerScreenPoint.y);
// set values for next check for actual change
mCurrentMapViewCoordinate = mMarkerCoordinate;
mCurrentBearing = bearing;
}
}
// rotate so arrow in points to bearing
if (mShowDirection) {
if (mMyBearingTrackingMode == MyBearingTracking.COMPASS && mMyLocationTrackingMode == MyLocationTracking.TRACKING_NONE) {
mMarkerScreenMatrix.preRotate((float)(mCompassMarkerDirection + mMapboxMap.getCameraPosition().bearing));
} else if (mMyBearingTrackingMode == MyBearingTracking.GPS) {
if (mMyLocationTrackingMode == MyLocationTracking.TRACKING_NONE) {
mMarkerScreenMatrix.preRotate((float)(mGpsMarkerDirection + mMapboxMap.getCameraPosition().bearing));
} else {
mMarkerScreenMatrix.preRotate(mGpsMarkerDirection);
}
}
}
// adjust accuracy circle
if (mShowAccuracy && !mStaleMarker) {
mAccuracyPath.reset();
mAccuracyPath.addCircle(0.0f, 0.0f,
(float) (mMarkerAccuracy / mMapboxMap.getProjection().getMetersPerPixelAtLatitude(
mMarkerCoordinate.getLatitude())),
Path.Direction.CW);
mAccuracyPath.computeBounds(mAccuracyBounds, false);
mAccuracyBounds.inset(-1.0f, -1.0f);
}
// invalidate changed pixels
if (mDirtyRect == null) {
mDirtyRect = new Rect();
mDirtyRectF = new RectF();
} else {
// the old marker location
invalidate(mDirtyRect);
}
RectF dotBounds = mShowDirection ? mUserLocationBearingDrawableBoundsF : mUserLocationDrawableBoundsF;
dotBounds = mStaleMarker ? mUserLocationStaleDrawableBoundsF : dotBounds;
RectF largerBounds = mShowAccuracy && !mStaleMarker && mAccuracyBounds.contains(dotBounds)
? mAccuracyBounds : dotBounds;
mMarkerScreenMatrix.mapRect(mDirtyRectF, largerBounds);
mDirtyRectF.roundOut(mDirtyRect);
invalidate(mDirtyRect); // the new marker location
} else {
setVisibility(View.INVISIBLE);
}
}
public Location getLocation() {
return mUserLocation;
}
/**
* 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 (mUserLocationListener == null) {
mUserLocationListener = new UserLocationListener(this);
}
// Register for Location Updates
locationServices.addLocationListener(mUserLocationListener);
} else {
// Disable location and user dot
setLocation(null);
// Deregister for Location Updates
locationServices.removeLocationListener(mUserLocationListener);
}
locationServices.toggleGPS(enableGps);
}
public void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) {
mMyBearingTrackingMode = myBearingTrackingMode;
if (myBearingTrackingMode == MyBearingTracking.COMPASS) {
mShowAccuracy = false;
mShowDirection = true;
mBearingChangeListener.onStart(getContext());
} else {
mBearingChangeListener.onStop();
if (myBearingTrackingMode == MyBearingTracking.GPS) {
mShowDirection = (mUserLocation != null) && mUserLocation.hasBearing();
} else {
mShowDirection = false;
}
}
update();
}
private class MyBearingListener implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private Sensor mMagnetometer;
private float[] mLastAccelerometer = new float[3];
private float[] mLastMagnetometer = new float[3];
private boolean mLastAccelerometerSet = false;
private boolean mLastMagnetometerSet = false;
private float[] mR = new float[9];
private float[] mOrientation = new float[3];
private float mCurrentDegree = 0f;
// Controls the sensor update rate in milliseconds
private static final int UPDATE_RATE_MS = 300;
// Compass data
private float mCompassBearing;
private long mCompassUpdateNextTimestamp = 0;
public MyBearingListener(Context context) {
mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}
public void onStart(Context context) {
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME);
}
public void onStop() {
mSensorManager.unregisterListener(this, mAccelerometer);
mSensorManager.unregisterListener(this, mMagnetometer);
}
public float getCompassBearing() {
return mCurrentDegree;
}
@Override
public void onSensorChanged(SensorEvent event) {
if (mPaused) {
return;
}
long currentTime = SystemClock.elapsedRealtime();
if (currentTime < mCompassUpdateNextTimestamp) {
return;
}
if (event.sensor == mAccelerometer) {
System.arraycopy(event.values, 0, mLastAccelerometer, 0, event.values.length);
mLastAccelerometerSet = true;
} else if (event.sensor == mMagnetometer) {
System.arraycopy(event.values, 0, mLastMagnetometer, 0, event.values.length);
mLastMagnetometerSet = true;
}
if (mLastAccelerometerSet && mLastMagnetometerSet) {
SensorManager.getRotationMatrix(mR, null, mLastAccelerometer, mLastMagnetometer);
SensorManager.getOrientation(mR, mOrientation);
float azimuthInRadians = mOrientation[0];
mCompassBearing = (float) (Math.toDegrees(azimuthInRadians) + 360) % 360;
if (mCompassBearing < 0) {
// only allow positive degrees
mCompassBearing += 360;
}
if (mCompassBearing > mCurrentDegree + 15 || mCompassBearing < mCurrentDegree - 15) {
mCurrentDegree = mCompassBearing;
setCompass(mCurrentDegree);
}
}
mCompassUpdateNextTimestamp = currentTime + UPDATE_RATE_MS;
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO add accuracy to the equiation
}
}
private static class UserLocationListener implements LocationListener {
private WeakReference mUserLocationView;
public UserLocationListener(UserLocationView userLocationView) {
mUserLocationView = new WeakReference<>(userLocationView);
}
/**
* Callback method for receiving location updates from LocationServices.
*
* @param location The new Location data
*/
@Override
public void onLocationChanged(Location location) {
UserLocationView locationView = mUserLocationView.get();
if (locationView != null && !locationView.isPaused()) {
locationView.setLocation(location);
}
}
}
private boolean isStale(Location location) {
if (location != null && mMyBearingTrackingMode != MyBearingTracking.COMPASS) {
long ageInNanos;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
ageInNanos = SystemClock.elapsedRealtimeNanos() -
location.getElapsedRealtimeNanos();
} else {
ageInNanos = (System.currentTimeMillis() - location.getTime()) * 1000 * 1000;
}
final long oneMinuteInNanos = 60L * 1000 * 1000 * 1000;
return ageInNanos > oneMinuteInNanos;
} else {
return false;
}
}
// Handles location updates from GPS
private void setLocation(Location location) {
// if null we should hide the marker
if (location == null) {
mShowMarker = false;
mShowDirection = false;
mShowAccuracy = false;
cancelAnimations();
mUserLocation = null;
return;
}
if (mMarkerCoordinateAnimator != null) {
mMarkerCoordinateAnimator.end();
mMarkerCoordinateAnimator = null;
}
if (mMarkerDirectionAnimator != null) {
mMarkerDirectionAnimator.end();
mMarkerDirectionAnimator = null;
}
if (mMarkerAccuracyAnimator != null) {
mMarkerAccuracyAnimator.end();
mMarkerAccuracyAnimator = null;
}
mShowMarker = true;
LatLng previousCoordinate;
if (mUserLocation == null) {
previousCoordinate = new LatLng(location);
} else {
previousCoordinate = new LatLng(mUserLocation);
}
if (mMyLocationTrackingMode == MyLocationTracking.TRACKING_NONE) {
// moving marker above map
mMarkerCoordinateAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
mMarkerCoordinateAnimator.setDuration(1000);
mMarkerCoordinateAnimator.addUpdateListener(new MarkerCoordinateAnimatorListener(
previousCoordinate, new LatLng(location)
));
mMarkerCoordinateAnimator.start();
mMarkerCoordinate = new LatLng(location);
} else {
// moving map under the tracker
mMarkerCoordinate = new LatLng(location);
}
if (mMyLocationTrackingMode == MyLocationTracking.TRACKING_NONE && mMyBearingTrackingMode == MyBearingTracking.GPS) {
// show GPS direction
mShowDirection = location.hasBearing();
if (mShowDirection) {
if (mUserLocation != null && mUserLocation.hasBearing()) {
mGpsMarkerDirection = mUserLocation.getBearing();
}
float oldDir = mGpsMarkerDirection;
float newDir = location.getBearing();
float diff = oldDir - newDir;
if (diff > 180.0f) {
newDir += 360.0f;
} else if (diff < -180.0f) {
newDir -= 360.f;
}
mMarkerDirectionAnimator = ObjectAnimator.ofFloat(this, "direction", oldDir, newDir);
mMarkerDirectionAnimator.setDuration(1000);
mMarkerDirectionAnimator.start();
}
} else if (mMyLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW && mMyBearingTrackingMode == MyBearingTracking.GPS) {
// always show north & rotate map below
mShowDirection = true;
mGpsMarkerDirection = 0;
}
mShowAccuracy = location.hasAccuracy();
if (mShowAccuracy) {
if (mUserLocation != null && mUserLocation.hasAccuracy()) {
mMarkerAccuracy = mUserLocation.getAccuracy();
}
mMarkerAccuracyAnimator = ObjectAnimator.ofFloat(this, "accuracy", location.getAccuracy());
mMarkerAccuracyAnimator.setDuration(1000);
mMarkerAccuracyAnimator.start();
}
mUserLocation = location;
updateOnNextFrame();
if (mOnMyLocationChangeListener != null) {
mOnMyLocationChangeListener.onMyLocationChange(location);
}
}
// handles compass sensor updates
private void setCompass(float bearing) {
if (mMyLocationTrackingMode == MyLocationTracking.TRACKING_NONE) {
// animate marker
mShowDirection = true;
float oldDir = mCompassMarkerDirection;
float newDir = bearing;
float diff = oldDir - newDir;
if (diff > 180.0f) {
newDir += 360.0f;
} else if (diff < -180.0f) {
newDir -= 360.f;
}
mMarkerDirectionAnimator = ObjectAnimator.ofFloat(this, "direction", oldDir, newDir);
mMarkerDirectionAnimator.setDuration(1000);
mMarkerDirectionAnimator.start();
mCompassMarkerDirection = bearing;
} else if (mMyLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
cancelAnimations();
if (mMyBearingTrackingMode == MyBearingTracking.COMPASS) {
// always show north & change map direction
mShowDirection = true;
mGpsMarkerDirection = 0;
mCompassMarkerDirection = 0;
update();
}
}
}
void updateOnNextFrame() {
mMapboxMap.invalidate();
}
public void onPause() {
mPaused = true;
toggleGps(false);
}
public void onResume() {
mPaused = false;
if (isEnabled()) {
toggleGps(true);
}
}
public void setOnMyLocationChangeListener(@Nullable MapboxMap.OnMyLocationChangeListener listener) {
mOnMyLocationChangeListener = listener;
}
// public for animator only
public float getDirection() {
if (mMyBearingTrackingMode == MyBearingTracking.COMPASS) {
return mCompassMarkerDirection;
}
return mGpsMarkerDirection;
}
// public for animator only
public void setDirection(float direction) {
if (mMyBearingTrackingMode == MyBearingTracking.COMPASS) {
mCompassMarkerDirection = direction % 360.0f;
} else {
mGpsMarkerDirection = direction % 360.0f;
}
updateOnNextFrame();
}
// public for animator only
public float getAccuracy() {
return mMarkerAccuracy;
}
// public for animator only
public void setAccuracy(float accuracy) {
mMarkerAccuracy = accuracy;
updateOnNextFrame();
}
private class MarkerCoordinateAnimatorListener implements ValueAnimator.AnimatorUpdateListener {
private double mFromLat;
private double mFromLng;
private double mToLat;
private double mToLng;
private MarkerCoordinateAnimatorListener(LatLng from, LatLng to) {
mFromLat = from.getLatitude();
mFromLng = from.getLongitude();
mToLat = to.getLatitude();
mToLng = to.getLongitude();
}
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float frac = animation.getAnimatedFraction();
double latitude = mFromLat + (mToLat - mFromLat) * frac;
double longitude = mFromLng + (mToLng - mFromLng) * frac;
mMarkerCoordinate.setLatitude(latitude);
mMarkerCoordinate.setLongitude(longitude);
updateOnNextFrame();
}
}
public void cancelAnimations() {
if (mMarkerCoordinateAnimator != null) {
mMarkerCoordinateAnimator.cancel();
mMarkerCoordinateAnimator = null;
}
if (mMarkerDirectionAnimator != null) {
mMarkerDirectionAnimator.cancel();
mMarkerDirectionAnimator = null;
}
if (mMarkerAccuracyAnimator != null) {
mMarkerAccuracyAnimator.cancel();
mMarkerAccuracyAnimator = null;
}
}
public boolean isPaused() {
return mPaused;
}
public PointF getMarkerScreenPoint() {
if (mMyLocationTrackingMode == MyLocationTracking.TRACKING_NONE) {
mMarkerScreenPoint = mProjection.toScreenLocation(mMarkerCoordinate);
} else {
int[] contentPadding = mMapboxMap.getPadding();
mMarkerScreenPoint = new PointF(((getMeasuredWidth() + contentPadding[0] - contentPadding[2]) / 2)
, ((getMeasuredHeight() - contentPadding[3] + contentPadding[1]) / 2));
}
return mMarkerScreenPoint;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy