diff options
author | Tobrun <tobrun.van.nuland@gmail.com> | 2016-12-06 13:46:49 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-06 13:46:49 +0100 |
commit | 9a9e7978db67276cfaab97e00f2b56eeb0222b12 (patch) | |
tree | 0da54e64117a64195ee46060e01d270a86c1e45d /platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java | |
parent | 890b681b182f7d538237604307da487f3619d1b1 (diff) | |
download | qtlocation-mapboxgl-9a9e7978db67276cfaab97e00f2b56eeb0222b12.tar.gz |
[android] - Refactor dependencies, introduce focused components (#7189)
* [android] - refactor dependencies
* ignore tests
Diffstat (limited to 'platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java')
-rw-r--r-- | platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java | 1806 |
1 files changed, 195 insertions, 1611 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java index 3fe9a67f3c..cd7caf395d 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java @@ -1,7 +1,5 @@ package com.mapbox.mapboxsdk.maps; -import android.Manifest; -import android.annotation.SuppressLint; import android.app.Activity; import android.app.Dialog; import android.app.Fragment; @@ -11,66 +9,47 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; -import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.PointF; -import android.graphics.RectF; import android.graphics.SurfaceTexture; -import android.location.Location; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.os.Bundle; import android.support.annotation.CallSuper; -import android.support.annotation.FloatRange; import android.support.annotation.IntDef; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.UiThread; -import android.support.v4.content.ContextCompat; -import android.support.v4.view.GestureDetectorCompat; -import android.support.v4.view.ScaleGestureDetectorCompat; import android.support.v7.app.AlertDialog; import android.text.TextUtils; import android.util.AttributeSet; -import timber.log.Timber; -import android.view.GestureDetector; -import android.view.InputDevice; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; -import android.view.ScaleGestureDetector; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.TextureView; import android.view.View; -import android.view.ViewConfiguration; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ZoomButtonsController; -import com.almeros.android.multitouch.gesturedetectors.RotateGestureDetector; -import com.almeros.android.multitouch.gesturedetectors.ShoveGestureDetector; -import com.almeros.android.multitouch.gesturedetectors.TwoFingerGestureDetector; import com.mapbox.mapboxsdk.MapboxAccountManager; import com.mapbox.mapboxsdk.R; -import com.mapbox.mapboxsdk.annotations.Annotation; import com.mapbox.mapboxsdk.annotations.InfoWindow; -import com.mapbox.mapboxsdk.annotations.Marker; -import com.mapbox.mapboxsdk.annotations.MarkerView; +import com.mapbox.mapboxsdk.annotations.MarkerViewManager; import com.mapbox.mapboxsdk.camera.CameraPosition; import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; import com.mapbox.mapboxsdk.constants.MapboxConstants; import com.mapbox.mapboxsdk.constants.MyBearingTracking; import com.mapbox.mapboxsdk.constants.MyLocationTracking; import com.mapbox.mapboxsdk.constants.Style; -import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.location.LocationListener; import com.mapbox.mapboxsdk.location.LocationServices; import com.mapbox.mapboxsdk.maps.widgets.CompassView; @@ -78,17 +57,15 @@ import com.mapbox.mapboxsdk.maps.widgets.MyLocationView; import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings; import com.mapbox.mapboxsdk.telemetry.MapboxEvent; import com.mapbox.mapboxsdk.telemetry.MapboxEventManager; -import com.mapbox.mapboxsdk.utils.ColorUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; -import java.util.Collections; import java.util.Hashtable; import java.util.Iterator; import java.util.List; -import static com.mapbox.mapboxsdk.utils.MathUtils.convertNativeBearing; +import timber.log.Timber; /** * <p> @@ -107,8 +84,6 @@ import static com.mapbox.mapboxsdk.utils.MathUtils.convertNativeBearing; public class MapView extends FrameLayout { private MapboxMap mapboxMap; - private IconManager iconManager; - private AnnotationManager annotationManager; private boolean initialLoad; private boolean destroyed; @@ -116,42 +91,18 @@ public class MapView extends FrameLayout { private NativeMapView nativeMapView; private boolean hasSurface = false; - private ViewGroup markerViewContainer; private CompassView compassView; - private ImageView logoView; - private ImageView attributionsView; private MyLocationView myLocationView; private LocationListener myLocationListener; - private Projection projection; + private MapGestureDetector mapGestureDetector; + private MapKeyListener mapKeyListener; - private ZoomButtonsController zoomButtonsController; private ConnectivityReceiver connectivityReceiver; - private float screenDensity = 1.0f; - - private TrackballLongPressTimeOut currentTrackballLongPressTimeOut; - private GestureDetectorCompat gestureDetector; - private ScaleGestureDetector scaleGestureDetector; - private RotateGestureDetector rotateGestureDetector; - private ShoveGestureDetector shoveGestureDetector; - private boolean twoTap = false; - private boolean zoomStarted = false; - private boolean dragStarted = false; - private boolean quickZoom = false; - private boolean scrollInProgress = false; - - private int contentPaddingLeft; - private int contentPaddingTop; - private int contentPaddingRight; - private int contentPaddingBottom; - - private PointF focalPoint; - - private String styleUrl = Style.MAPBOX_STREETS; - private boolean styleWasSet = false; - - private List<OnMapReadyCallback> onMapReadyCallbackList; + + private List<OnMapReadyCallback> onMapReadyCallbackList = new ArrayList<>(); private SnapshotRequest snapshotRequest; + private ZoomButtonsController zoomButtonsController; private boolean onStartCalled; private boolean onStopCalled; @@ -175,21 +126,20 @@ public class MapView extends FrameLayout { } @UiThread - public MapView(@NonNull Context context, @Nullable MapboxMapOptions options) { + public MapView(@NonNull Context context, @NonNull MapboxMapOptions options) { super(context); initialize(context, options); } - private void initialize(@NonNull Context context, @NonNull MapboxMapOptions options) { + private void initialize(@NonNull final Context context, @NonNull final MapboxMapOptions options) { if (isInEditMode()) { // if we are in an editor mode we show an image of a map LayoutInflater.from(context).inflate(R.layout.mapbox_mapview_preview, this); return; } + // TODO distill into singular purpose methods/classes initialLoad = true; - onMapReadyCallbackList = new ArrayList<>(); - View view = LayoutInflater.from(context).inflate(R.layout.mapbox_mapview_internal, this); setWillNotDraw(false); @@ -204,153 +154,61 @@ public class MapView extends FrameLayout { } nativeMapView = new NativeMapView(this); - iconManager = new IconManager(nativeMapView); - mapboxMap = new MapboxMap(this, iconManager); - annotationManager = mapboxMap.getAnnotationManager(); - projection = mapboxMap.getProjection(); + + // inflate overlain Views + compassView = (CompassView) view.findViewById(R.id.compassView); + myLocationView = (MyLocationView) view.findViewById(R.id.userLocationView); + ImageView logoView = (ImageView) view.findViewById(R.id.logoView); + ImageView attributionsView = (ImageView) view.findViewById(R.id.attributionView); + attributionsView.setOnClickListener(new AttributionOnClickListener(this)); + ViewGroup markerViewContainer = (ViewGroup) findViewById(R.id.markerViewContainer); + + // interface for focal point invalidation + FocalPointInvalidator focalPointInvalidator = new FocalPointInvalidator(); + + // interface for registering touch listeners + RegisterTouchListener registerTouchListener = new RegisterTouchListener(); + + // setup components for MapboxMap creation + Projection projection = new Projection(nativeMapView); + UiSettings uiSettings = new UiSettings(projection, focalPointInvalidator, compassView, attributionsView, logoView); + TrackingSettings trackingSettings = new TrackingSettings(myLocationView, uiSettings, focalPointInvalidator); + MyLocationViewSettings myLocationViewSettings = new MyLocationViewSettings(projection, myLocationView, trackingSettings); + MarkerViewManager markerViewManager = new MarkerViewManager(markerViewContainer); + AnnotationManager annotationManager = new AnnotationManager(nativeMapView, this, markerViewManager); + Transform transform = new Transform(nativeMapView, annotationManager.getMarkerViewManager(), trackingSettings); + mapboxMap = new MapboxMap(nativeMapView, transform, uiSettings, trackingSettings, myLocationViewSettings, projection, registerTouchListener, annotationManager); + + // active user input + mapGestureDetector = new MapGestureDetector(context, mapboxMap.getTransform(), projection, uiSettings, trackingSettings, annotationManager); + mapKeyListener = new MapKeyListener(mapboxMap.getTransform(), trackingSettings, uiSettings); + + // attach widgets to MapboxMap + compassView.setMapboxMap(mapboxMap); + myLocationView.setMapboxMap(mapboxMap); // Ensure this view is interactable setClickable(true); setLongClickable(true); setFocusable(true); setFocusableInTouchMode(true); + requestDisallowInterceptTouchEvent(true); requestFocus(); - // Touch gesture detectors - gestureDetector = new GestureDetectorCompat(context, new GestureListener()); - gestureDetector.setIsLongpressEnabled(true); - scaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureListener()); - ScaleGestureDetectorCompat.setQuickScaleEnabled(scaleGestureDetector, true); - rotateGestureDetector = new RotateGestureDetector(context, new RotateGestureListener()); - shoveGestureDetector = new ShoveGestureDetector(context, new ShoveGestureListener()); - - zoomButtonsController = new ZoomButtonsController(this); - zoomButtonsController.setZoomSpeed(MapboxConstants.ANIMATION_DURATION); - zoomButtonsController.setOnZoomListener(new OnZoomListener()); - // Connectivity onConnectivityChanged(isConnected()); - markerViewContainer = (ViewGroup) view.findViewById(R.id.markerViewContainer); - - myLocationView = (MyLocationView) view.findViewById(R.id.userLocationView); - myLocationView.setMapboxMap(mapboxMap); - - compassView = (CompassView) view.findViewById(R.id.compassView); - compassView.setMapboxMap(mapboxMap); - - logoView = (ImageView) view.findViewById(R.id.logoView); - - // Setup Attributions control - attributionsView = (ImageView) view.findViewById(R.id.attributionView); - attributionsView.setOnClickListener(new AttributionOnClickListener(this)); - - screenDensity = context.getResources().getDisplayMetrics().density; + // configure the zoom button controller + zoomButtonsController = new ZoomButtonsController(MapView.this); + zoomButtonsController.setZoomSpeed(MapboxConstants.ANIMATION_DURATION); + zoomButtonsController.setOnZoomListener(new OnZoomListener(mapboxMap)); - setInitialState(options); + mapboxMap.initialise(context, options); // Shows the zoom controls if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)) { - mapboxMap.getUiSettings().setZoomControlsEnabled(true); - } - } - - private void setInitialState(MapboxMapOptions options) { - mapboxMap.setDebugActive(options.getDebugActive()); - - CameraPosition position = options.getCamera(); - if (position != null && !position.equals(CameraPosition.DEFAULT)) { - mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(position)); - myLocationView.setTilt(position.tilt); - } - - // api base url - String apiBaseUrl = options.getApiBaseUrl(); - if (!TextUtils.isEmpty(apiBaseUrl)) { - setApiBaseUrl(apiBaseUrl); - } - - // access token - String accessToken = options.getAccessToken(); - if (!TextUtils.isEmpty(accessToken)) { - mapboxMap.setAccessToken(accessToken); - } - - // style url - String style = options.getStyle(); - if (!TextUtils.isEmpty(style)) { - styleUrl = style; - } - - // MyLocationView - MyLocationViewSettings myLocationViewSettings = mapboxMap.getMyLocationViewSettings(); - myLocationViewSettings.setForegroundDrawable( - options.getMyLocationForegroundDrawable(), options.getMyLocationForegroundBearingDrawable()); - myLocationViewSettings.setForegroundTintColor(options.getMyLocationForegroundTintColor()); - myLocationViewSettings.setBackgroundDrawable( - options.getMyLocationBackgroundDrawable(), options.getMyLocationBackgroundPadding()); - myLocationViewSettings.setBackgroundTintColor(options.getMyLocationBackgroundTintColor()); - myLocationViewSettings.setAccuracyAlpha(options.getMyLocationAccuracyAlpha()); - myLocationViewSettings.setAccuracyTintColor(options.getMyLocationAccuracyTintColor()); - mapboxMap.setMyLocationEnabled(options.getLocationEnabled()); - - // Enable gestures - UiSettings uiSettings = mapboxMap.getUiSettings(); - uiSettings.setZoomGesturesEnabled(options.getZoomGesturesEnabled()); - uiSettings.setZoomGestureChangeAllowed(options.getZoomGesturesEnabled()); - uiSettings.setScrollGesturesEnabled(options.getScrollGesturesEnabled()); - uiSettings.setScrollGestureChangeAllowed(options.getScrollGesturesEnabled()); - uiSettings.setRotateGesturesEnabled(options.getRotateGesturesEnabled()); - uiSettings.setRotateGestureChangeAllowed(options.getRotateGesturesEnabled()); - uiSettings.setTiltGesturesEnabled(options.getTiltGesturesEnabled()); - uiSettings.setTiltGestureChangeAllowed(options.getTiltGesturesEnabled()); - - // Ui Controls - uiSettings.setZoomControlsEnabled(options.getZoomControlsEnabled()); - - // Zoom - mapboxMap.setMaxZoom(options.getMaxZoom()); - mapboxMap.setMinZoom(options.getMinZoom()); - - // Compass - uiSettings.setCompassEnabled(options.getCompassEnabled()); - uiSettings.setCompassGravity(options.getCompassGravity()); - int[] compassMargins = options.getCompassMargins(); - if (compassMargins != null) { - uiSettings.setCompassMargins(compassMargins[0], compassMargins[1], compassMargins[2], compassMargins[3]); - } else { - int tenDp = (int) getResources().getDimension(R.dimen.mapbox_ten_dp); - uiSettings.setCompassMargins(tenDp, tenDp, tenDp, tenDp); - } - uiSettings.setCompassFadeFacingNorth(options.getCompassFadeFacingNorth()); - - // Logo - uiSettings.setLogoEnabled(options.getLogoEnabled()); - uiSettings.setLogoGravity(options.getLogoGravity()); - int[] logoMargins = options.getLogoMargins(); - if (logoMargins != null) { - uiSettings.setLogoMargins(logoMargins[0], logoMargins[1], logoMargins[2], logoMargins[3]); - } else { - int sixteenDp = (int) getResources().getDimension(R.dimen.mapbox_sixteen_dp); - uiSettings.setLogoMargins(sixteenDp, sixteenDp, sixteenDp, sixteenDp); - } - - // Attribution - uiSettings.setAttributionEnabled(options.getAttributionEnabled()); - uiSettings.setAttributionGravity(options.getAttributionGravity()); - int[] attributionMargins = options.getAttributionMargins(); - if (attributionMargins != null) { - uiSettings.setAttributionMargins(attributionMargins[0], attributionMargins[1], attributionMargins[2], attributionMargins[3]); - } else { - Resources resources = getResources(); - int sevenDp = (int) resources.getDimension(R.dimen.mapbox_seven_dp); - int seventySixDp = (int) resources.getDimension(R.dimen.mapbox_seventy_six_dp); - uiSettings.setAttributionMargins(seventySixDp, sevenDp, sevenDp, sevenDp); + uiSettings.setZoomControlsEnabled(true); } - - int attributionTintColor = options.getAttributionTintColor(); - uiSettings.setAttributionTintColor(attributionTintColor != -1 - ? attributionTintColor : ColorUtils.getPrimaryColor(getContext())); } // @@ -370,17 +228,20 @@ public class MapView extends FrameLayout { */ @UiThread public void onCreate(@Nullable Bundle savedInstanceState) { + // TODO distill into singular purpose methods/classes String accessToken = mapboxMap.getAccessToken(); if (TextUtils.isEmpty(accessToken)) { accessToken = MapboxAccountManager.getInstance().getAccessToken(); - mapboxMap.setAccessToken(accessToken); + nativeMapView.setAccessToken(accessToken); } else { // user provided access token through xml attributes, need to start MapboxAccountManager MapboxAccountManager.start(getContext(), accessToken); + nativeMapView.setAccessToken(accessToken); } // Force a check for an access token MapboxAccountManager.validateAccessToken(accessToken); + nativeMapView.setAccessToken(accessToken); if (savedInstanceState != null && savedInstanceState.getBoolean(MapboxConstants.STATE_HAS_SAVED_STATE)) { @@ -427,7 +288,11 @@ public class MapView extends FrameLayout { , savedInstanceState.getInt(MapboxConstants.STATE_ATTRIBUTION_MARGIN_BOTTOM)); mapboxMap.setDebugActive(savedInstanceState.getBoolean(MapboxConstants.STATE_DEBUG_ACTIVE)); - styleUrl = savedInstanceState.getString(MapboxConstants.STATE_STYLE_URL); + + String styleUrl = savedInstanceState.getString(MapboxConstants.STATE_STYLE_URL); + if (!TextUtils.isEmpty(styleUrl)) { + nativeMapView.setStyleUrl(savedInstanceState.getString(MapboxConstants.STATE_STYLE_URL)); + } // User location try { @@ -462,11 +327,12 @@ public class MapView extends FrameLayout { addOnMapChangedListener(new OnMapChangedListener() { @Override public void onMapChanged(@MapChange int change) { + + // TODO extract logic into separate OnMapReady and Update Component if (change == DID_FINISH_LOADING_STYLE && initialLoad) { initialLoad = false; - iconManager.reloadIcons(); - annotationManager.reloadMarkers(); - annotationManager.adjustTopOffsetPixels(mapboxMap); + mapboxMap.getAnnotationManager().reloadMarkers(); + mapboxMap.getAnnotationManager().adjustTopOffsetPixels(mapboxMap); // Notify listeners the map is ready if (onMapReadyCallbackList.size() > 0) { @@ -484,7 +350,7 @@ public class MapView extends FrameLayout { } else if (change == REGION_IS_CHANGING || change == REGION_DID_CHANGE || change == DID_FINISH_LOADING_MAP) { mapboxMap.getMarkerViewManager().scheduleViewMarkerInvalidation(); - compassView.update(getDirection()); + compassView.update(mapboxMap.getTransform().getBearing()); myLocationView.update(); mapboxMap.getMarkerViewManager().update(); @@ -517,7 +383,7 @@ public class MapView extends FrameLayout { outState.putBoolean(MapboxConstants.STATE_HAS_SAVED_STATE, true); outState.putParcelable(MapboxConstants.STATE_CAMERA_POSITION, mapboxMap.getCameraPosition()); outState.putBoolean(MapboxConstants.STATE_DEBUG_ACTIVE, mapboxMap.isDebugActive()); - outState.putString(MapboxConstants.STATE_STYLE_URL, styleUrl); + outState.putString(MapboxConstants.STATE_STYLE_URL, nativeMapView.getStyleUrl()); outState.putBoolean(MapboxConstants.STATE_MY_LOCATION_ENABLED, mapboxMap.isMyLocationEnabled()); // TrackingSettings @@ -579,9 +445,9 @@ public class MapView extends FrameLayout { nativeMapView.update(); myLocationView.onStart(); - // In case that no style was set or was loaded through MapboxMapOptions - if (!styleWasSet) { - setStyleUrl(styleUrl); + if (TextUtils.isEmpty(nativeMapView.getStyleUrl())) { + // if user hasn't loaded a Style yet, load default for them instead + nativeMapView.setStyleUrl(Style.MAPBOX_STREETS); } } @@ -640,16 +506,63 @@ public class MapView extends FrameLayout { nativeMapView = null; } - void setFocalPoint(PointF focalPoint) { - if (focalPoint == null) { - // resetting focal point, - UiSettings uiSettings = mapboxMap.getUiSettings(); - // need to validate if we need to reset focal point with user provided one - if (uiSettings.getFocalPoint() != null) { - focalPoint = uiSettings.getFocalPoint(); + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + if (mapboxMap.getUiSettings().isZoomControlsEnabled()) { + zoomButtonsController.setVisible(true); } } - this.focalPoint = focalPoint; + return mapGestureDetector.onTouchEvent(event) || super.onTouchEvent(event); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + return mapKeyListener.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event); + } + + @Override + public boolean onKeyLongPress(int keyCode, KeyEvent event) { + return mapKeyListener.onKeyLongPress(keyCode, event) || super.onKeyLongPress(keyCode, event); + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + return mapKeyListener.onKeyUp(keyCode, event) || super.onKeyUp(keyCode, event); + } + + @Override + public boolean onTrackballEvent(MotionEvent event) { + return mapKeyListener.onTrackballEvent(event) || super.onTrackballEvent(event); + } + + @Override + public boolean onGenericMotionEvent(MotionEvent event) { + return mapGestureDetector.onGenericMotionEvent(event) || super.onGenericMotionEvent(event); + } + + @Override + public boolean onHoverEvent(MotionEvent event) { + switch (event.getActionMasked()) { + case MotionEvent.ACTION_HOVER_ENTER: + case MotionEvent.ACTION_HOVER_MOVE: + // Show the zoom controls + if (mapboxMap.getUiSettings().isZoomControlsEnabled()) { + zoomButtonsController.setVisible(true); + } + return true; + + case MotionEvent.ACTION_HOVER_EXIT: + // Hide the zoom controls + if (mapboxMap.getUiSettings().isZoomControlsEnabled()) { + zoomButtonsController.setVisible(false); + } + return true; + + default: + // We are not interested in this event + return false; + } } /** @@ -675,179 +588,6 @@ public class MapView extends FrameLayout { }); } - // - // LatLng / CenterCoordinate - // - - LatLng getLatLng() { - return nativeMapView.getLatLng(); - } - - // - // Pitch / Tilt - // - - double getTilt() { - return nativeMapView.getPitch(); - } - - void setTilt(Double pitch) { - mapboxMap.getMarkerViewManager().setTilt(pitch.floatValue()); - myLocationView.setTilt(pitch); - nativeMapView.setPitch(pitch, 0); - } - - // - // Center coordinate - // - - LatLng getCenterCoordinate() { - return nativeMapView.getLatLng(); - } - - void setCenterCoordinate(LatLng centerCoordinate) { - nativeMapView.setLatLng(centerCoordinate); - } - - // - // Direction - // - - double getDirection() { - if (destroyed) { - return 0; - } - - return convertNativeBearing(nativeMapView.getBearing()); - } - - void setDirection(@FloatRange(from = MapboxConstants.MINIMUM_DIRECTION, to = MapboxConstants.MAXIMUM_DIRECTION) double direction) { - if (destroyed) { - return; - } - setDirection(direction, false); - } - - void setDirection(@FloatRange(from = MapboxConstants.MINIMUM_DIRECTION, to = MapboxConstants.MAXIMUM_DIRECTION) double direction, boolean animated) { - if (destroyed) { - return; - } - long duration = animated ? MapboxConstants.ANIMATION_DURATION : 0; - mapboxMap.cancelTransitions(); - // Out of range directions are normalised in setBearing - nativeMapView.setBearing(-direction, duration); - } - - void resetNorth() { - if (destroyed) { - return; - } - myLocationView.setBearing(0); - mapboxMap.cancelTransitions(); - nativeMapView.resetNorth(); - } - - // - // Content padding - // - - int getContentPaddingLeft() { - return contentPaddingLeft; - } - - int getContentPaddingTop() { - return contentPaddingTop; - } - - int getContentPaddingRight() { - return contentPaddingRight; - } - - int getContentPaddingBottom() { - return contentPaddingBottom; - } - - // - // Zoom - // - - double getZoom() { - if (destroyed) { - return 0; - } - return nativeMapView.getZoom(); - } - - void setMinZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double minZoom) { - if (destroyed) { - return; - } - nativeMapView.setMinZoom(minZoom); - } - - double getMinZoom() { - if (destroyed) { - return 0; - } - return nativeMapView.getMinZoom(); - } - - void setMaxZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double maxZoom) { - if (destroyed) { - return; - } - nativeMapView.setMaxZoom(maxZoom); - } - - double getMaxZoom() { - if (destroyed) { - return 0; - } - return nativeMapView.getMaxZoom(); - } - - // Zoom in or out - private void zoom(boolean zoomIn) { - zoom(zoomIn, -1.0f, -1.0f); - } - - private void zoom(boolean zoomIn, float x, float y) { - // Cancel any animation - mapboxMap.cancelTransitions(); - - if (zoomIn) { - nativeMapView.scaleBy(2.0, x / screenDensity, y / screenDensity, MapboxConstants.ANIMATION_DURATION); - } else { - nativeMapView.scaleBy(0.5, x / screenDensity, y / screenDensity, MapboxConstants.ANIMATION_DURATION); - } - } - - // - // Debug - // - - boolean isDebugActive() { - return !destroyed && nativeMapView.getDebug(); - } - - void setDebugActive(boolean debugActive) { - if (destroyed) { - return; - } - nativeMapView.setDebug(debugActive); - } - - void cycleDebugOptions() { - if (destroyed) { - return; - } - nativeMapView.cycleDebugOptions(); - } - - // - // Styling - // - /** * <p> * Loads a new map style from the specified URL. @@ -886,57 +626,9 @@ public class MapView extends FrameLayout { setAccessToken(MapboxAccountManager.getInstance().getAccessToken()); } - styleUrl = url; nativeMapView.setStyleUrl(url); - styleWasSet = true; - } - - /** - * <p> - * Loads a new map style from the specified bundled style. - * </p> - * <p> - * This method is asynchronous and will return immediately before the style finishes loading. - * If you wish to wait for the map to finish loading listen for the {@link MapView#DID_FINISH_LOADING_MAP} event. - * </p> - * If the style fails to load or an invalid style URL is set, the map view will become blank. - * An error message will be logged in the Android logcat and {@link MapView#DID_FAIL_LOADING_MAP} event will be sent. - * - * @param style The bundled style. Accepts one of the values from {@link Style}. - * @see Style - */ - @UiThread - public void setStyle(@Style.StyleUrl String style) { - setStyleUrl(style); - } - - /** - * <p> - * Returns the map style currently displayed in the map view. - * </p> - * If the default style is currently displayed, a URL will be returned instead of null. - * - * @return The URL of the map style. - */ - @UiThread - @NonNull - public String getStyleUrl() { - return styleUrl; } - // - // API Base URL - // - - @UiThread - void setApiBaseUrl(@NonNull String baseUrl) { - nativeMapView.setApiBaseUrl(baseUrl); - } - - // - // Access token - // - /** * <p> * DEPRECATED @see MapboxAccountManager#start(String) @@ -989,78 +681,6 @@ public class MapView extends FrameLayout { } // - // Projection - // - - /* - * Internal use only, use Projection#fromScreenLocation instead - */ - LatLng fromNativeScreenLocation(@NonNull PointF point) { - if (destroyed) { - return new LatLng(); - } - return nativeMapView.latLngForPixel(point); - } - - /* - * Internal use only, use Projection#toScreenLocation instead. - */ - PointF toNativeScreenLocation(@NonNull LatLng location) { - if (destroyed || location == null) { - return new PointF(); - } - return nativeMapView.pixelForLatLng(location); - } - - /** - * @return the ViewGroup containing the marker views - */ - public ViewGroup getMarkerViewContainer() { - return markerViewContainer; - } - - void setContentPadding(int left, int top, int right, int bottom) { - if (destroyed) { - return; - } - -// if (left == contentPaddingLeft && top == contentPaddingTop && right == contentPaddingRight && bottom == contentPaddingBottom) { -// return; -// } - - contentPaddingLeft = left; - contentPaddingTop = top; - contentPaddingRight = right; - contentPaddingBottom = bottom; - - int[] userLocationViewPadding = mapboxMap.getMyLocationViewSettings().getPadding(); - left += userLocationViewPadding[0]; - top += userLocationViewPadding[1]; - right += userLocationViewPadding[2]; - bottom += userLocationViewPadding[3]; - - nativeMapView.setContentPadding(top / screenDensity, left / screenDensity, bottom / screenDensity, right / screenDensity); - } - - public void invalidateContentPadding() { - setContentPadding(contentPaddingLeft, contentPaddingTop, contentPaddingRight, contentPaddingBottom); - - if (!mapboxMap.getTrackingSettings().isLocationTrackingDisabled()) { - setFocalPoint(new PointF(myLocationView.getCenterX(), myLocationView.getCenterY())); - } else { - setFocalPoint(null); - } - } - - double getMetersPerPixelAtLatitude(@FloatRange(from = -180, to = 180) double latitude) { - if (destroyed) { - return 0; - } - - return nativeMapView.getMetersPerPixelAtLatitude(latitude, getZoom()) / screenDensity; - } - - // // Rendering // @@ -1095,16 +715,8 @@ public class MapView extends FrameLayout { } if (!isInEditMode()) { - nativeMapView.resizeView((int) (width / screenDensity), (int) (height / screenDensity)); - } - } - - double getScale() { - if (destroyed) { - return 0; + nativeMapView.resizeView(width, height); } - - return nativeMapView.getScale(); } private class SurfaceCallback implements SurfaceHolder.Callback { @@ -1181,7 +793,8 @@ public class MapView extends FrameLayout { if (destroyed) { return; } - compassView.update(getDirection()); + // TODO move to transform. java + compassView.update(mapboxMap.getTransform().getBearing()); myLocationView.update(); mapboxMap.getMarkerViewManager().update(); @@ -1191,52 +804,6 @@ public class MapView extends FrameLayout { } } - void updateCameraPosition(@NonNull CameraPosition position) { - myLocationView.setCameraPosition(position); - mapboxMap.getMarkerViewManager().setTilt((float) position.tilt); - } - - double getBearing() { - if (destroyed) { - return 0; - } - - double direction = -nativeMapView.getBearing(); - - while (direction > 360) { - direction -= 360; - } - while (direction < 0) { - direction += 360; - } - - return direction; - } - - void setBearing(double bearing) { - if (destroyed) { - return; - } - myLocationView.setBearing(bearing); - nativeMapView.setBearing(bearing); - } - - void setBearing(double bearing, long duration) { - if (destroyed) { - return; - } - myLocationView.setBearing(bearing); - nativeMapView.setBearing(bearing, duration); - } - - void setBearing(double bearing, float focalX, float focalY) { - if (destroyed) { - return; - } - myLocationView.setBearing(bearing); - nativeMapView.setBearing(bearing, focalX, focalY); - } - // // View events // @@ -1267,898 +834,8 @@ public class MapView extends FrameLayout { return; } - // Required by ZoomButtonController (from Android SDK documentation) - if (visibility == View.VISIBLE) { - if (mapboxMap != null && mapboxMap.getUiSettings().isZoomControlsEnabled()) { - zoomButtonsController.setVisible(true); - } - } else { - if (mapboxMap != null && mapboxMap.getUiSettings().isZoomControlsEnabled()) { - zoomButtonsController.setVisible(false); - } - } - } - - // - // Touch events - // - - /** - * Helper method for tracking gesture events - * - * @param gestureId Type of Gesture See {@see MapboxEvent#GESTURE_SINGLETAP MapboxEvent#GESTURE_DOUBLETAP MapboxEvent#GESTURE_TWO_FINGER_SINGLETAP MapboxEvent#GESTURE_QUICK_ZOOM MapboxEvent#GESTURE_PAN_START MapboxEvent#GESTURE_PINCH_START MapboxEvent#GESTURE_ROTATION_START MapboxEvent#GESTURE_PITCH_START} - * @param xCoordinate Original x screen coordinate at start of gesture - * @param yCoordinate Original y screen cooridnate at start of gesture - */ - private void trackGestureEvent(@NonNull String gestureId, float xCoordinate, float yCoordinate) { - LatLng tapLatLng = projection.fromScreenLocation(new PointF(xCoordinate, yCoordinate)); - - // NaN and Infinite checks to prevent JSON errors at send to server time - if (Double.isNaN(tapLatLng.getLatitude()) || Double.isNaN(tapLatLng.getLongitude())) { - Timber.d("trackGestureEvent() has a NaN lat or lon. Returning."); - return; - } - - if (Double.isInfinite(tapLatLng.getLatitude()) || Double.isInfinite(tapLatLng.getLongitude())) { - Timber.d("trackGestureEvent() has an Infinite lat or lon. Returning."); - return; - } - - Hashtable<String, Object> evt = new Hashtable<>(); - evt.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_MAP_CLICK); - evt.put(MapboxEvent.ATTRIBUTE_CREATED, MapboxEventManager.generateCreateDate()); - evt.put(MapboxEvent.KEY_GESTURE_ID, gestureId); - evt.put(MapboxEvent.KEY_LATITUDE, tapLatLng.getLatitude()); - evt.put(MapboxEvent.KEY_LONGITUDE, tapLatLng.getLongitude()); - evt.put(MapboxEvent.KEY_ZOOM, mapboxMap.getCameraPosition().zoom); - - MapboxEventManager.getMapboxEventManager().pushEvent(evt); - } - - /** - * Helper method for tracking DragEnd gesture event - * See {@see MapboxEvent#TYPE_MAP_DRAGEND} - * - * @param xCoordinate Original x screen coordinate at end of drag - * @param yCoordinate Orginal y screen coordinate at end of drag - */ - private void trackGestureDragEndEvent(float xCoordinate, float yCoordinate) { - LatLng tapLatLng = projection.fromScreenLocation(new PointF(xCoordinate, yCoordinate)); - - // NaN and Infinite checks to prevent JSON errors at send to server time - if (Double.isNaN(tapLatLng.getLatitude()) || Double.isNaN(tapLatLng.getLongitude())) { - Timber.d("trackGestureDragEndEvent() has a NaN lat or lon. Returning."); - return; - } - - if (Double.isInfinite(tapLatLng.getLatitude()) || Double.isInfinite(tapLatLng.getLongitude())) { - Timber.d("trackGestureDragEndEvent() has an Infinite lat or lon. Returning."); - return; - } - - Hashtable<String, Object> evt = new Hashtable<>(); - evt.put(MapboxEvent.ATTRIBUTE_EVENT, MapboxEvent.TYPE_MAP_DRAGEND); - evt.put(MapboxEvent.ATTRIBUTE_CREATED, MapboxEventManager.generateCreateDate()); - evt.put(MapboxEvent.KEY_LATITUDE, tapLatLng.getLatitude()); - evt.put(MapboxEvent.KEY_LONGITUDE, tapLatLng.getLongitude()); - evt.put(MapboxEvent.KEY_ZOOM, mapboxMap.getCameraPosition().zoom); - - MapboxEventManager.getMapboxEventManager().pushEvent(evt); - } - - // Called when user touches the screen, all positions are absolute - @Override - public boolean onTouchEvent(@NonNull MotionEvent event) { - // Check and ignore non touch or left clicks - if (destroyed) { - return super.onTouchEvent(event); - } - - if ((event.getButtonState() != 0) && (event.getButtonState() != MotionEvent.BUTTON_PRIMARY)) { - return false; - } - - // Check two finger gestures first - rotateGestureDetector.onTouchEvent(event); - scaleGestureDetector.onTouchEvent(event); - shoveGestureDetector.onTouchEvent(event); - - // Handle two finger tap - switch (event.getActionMasked()) { - case MotionEvent.ACTION_DOWN: - // First pointer down - nativeMapView.setGestureInProgress(true); - break; - - case MotionEvent.ACTION_POINTER_DOWN: - // Second pointer down - twoTap = event.getPointerCount() == 2 - && mapboxMap.getUiSettings().isZoomGesturesEnabled(); - if (twoTap) { - // Confirmed 2nd Finger Down - trackGestureEvent(MapboxEvent.GESTURE_TWO_FINGER_SINGLETAP, event.getX(), event.getY()); - } - break; - - case MotionEvent.ACTION_POINTER_UP: - // Second pointer up - break; - - case MotionEvent.ACTION_UP: - // First pointer up - long tapInterval = event.getEventTime() - event.getDownTime(); - boolean isTap = tapInterval <= ViewConfiguration.getTapTimeout(); - boolean inProgress = rotateGestureDetector.isInProgress() - || scaleGestureDetector.isInProgress() - || shoveGestureDetector.isInProgress(); - - if (twoTap && isTap && !inProgress) { - if (focalPoint != null) { - zoom(false, focalPoint.x, focalPoint.y); - } else { - PointF focalPoint = TwoFingerGestureDetector.determineFocalPoint(event); - zoom(false, focalPoint.x, focalPoint.y); - } - twoTap = false; - return true; - } - - // Scroll / Pan Has Stopped - if (scrollInProgress) { - trackGestureDragEndEvent(event.getX(), event.getY()); - scrollInProgress = false; - } - - twoTap = false; - nativeMapView.setGestureInProgress(false); - break; - - case MotionEvent.ACTION_CANCEL: - twoTap = false; - nativeMapView.setGestureInProgress(false); - break; - } - - boolean retVal = gestureDetector.onTouchEvent(event); - return retVal || super.onTouchEvent(event); - } - - // This class handles one finger gestures - private class GestureListener extends GestureDetector.SimpleOnGestureListener { - - // Must always return true otherwise all events are ignored - @Override - @SuppressLint("ResourceType") - public boolean onDown(MotionEvent event) { - // Show the zoom controls - if (mapboxMap.getUiSettings().isZoomControlsEnabled()) { - zoomButtonsController.setVisible(true); - } - return true; - } - - // Called for double taps - @Override - public boolean onDoubleTapEvent(MotionEvent e) { - if (destroyed || !mapboxMap.getUiSettings().isZoomGesturesEnabled()) { - return false; - } - - switch (e.getAction()) { - case MotionEvent.ACTION_DOWN: - break; - case MotionEvent.ACTION_MOVE: - break; - case MotionEvent.ACTION_UP: - if (quickZoom) { - // insert here? - quickZoom = false; - break; - } - - // Single finger double tap - if (focalPoint != null) { - // User provided focal point - zoom(true, focalPoint.x, focalPoint.y); - } else { - // Zoom in on gesture - zoom(true, e.getX(), e.getY()); - } - break; - } - - trackGestureEvent(MapboxEvent.GESTURE_DOUBLETAP, e.getX(), e.getY()); - - return true; - } - - @Override - public boolean onSingleTapUp(MotionEvent motionEvent) { - if (destroyed) { - return false; - } - // Cancel any animation - mapboxMap.cancelTransitions(); - return true; - } - - @Override - public boolean onSingleTapConfirmed(MotionEvent motionEvent) { - List<Marker> selectedMarkers = mapboxMap.getSelectedMarkers(); - - PointF tapPoint = new PointF(motionEvent.getX(), motionEvent.getY()); - float toleranceSides = 4 * screenDensity; - float toleranceTopBottom = 10 * screenDensity; - - RectF tapRect = new RectF(tapPoint.x - iconManager.getAverageIconWidth() / 2 - toleranceSides, - tapPoint.y - iconManager.getAverageIconHeight() / 2 - toleranceTopBottom, - tapPoint.x + iconManager.getAverageIconWidth() / 2 + toleranceSides, - tapPoint.y + iconManager.getAverageIconHeight() / 2 + toleranceTopBottom); - - List<Marker> nearbyMarkers = annotationManager.getMarkersInRect(tapRect); - long newSelectedMarkerId = -1; - - if (nearbyMarkers != null && nearbyMarkers.size() > 0) { - Collections.sort(nearbyMarkers); - for (Marker nearbyMarker : nearbyMarkers) { - boolean found = false; - for (Marker selectedMarker : selectedMarkers) { - if (selectedMarker.equals(nearbyMarker)) { - found = true; - } - } - if (!found) { - newSelectedMarkerId = nearbyMarker.getId(); - break; - } - } - } - - if (newSelectedMarkerId >= 0) { - List<Annotation> annotations = mapboxMap.getAnnotations(); - int count = annotations.size(); - for (int i = 0; i < count; i++) { - Annotation annotation = annotations.get(i); - if (annotation instanceof Marker) { - if (annotation.getId() == newSelectedMarkerId) { - if (selectedMarkers.isEmpty() || !selectedMarkers.contains(annotation)) { - if (!(annotation instanceof MarkerView)) { - mapboxMap.selectMarker((Marker) annotation); - } else { - mapboxMap.getMarkerViewManager().onClickMarkerView((MarkerView) annotation); - } - } - break; - } - } - } - } else { - if (mapboxMap.getUiSettings().isDeselectMarkersOnTap()) { - // deselect any selected marker - mapboxMap.deselectMarkers(); - } - - // notify app of map click - MapboxMap.OnMapClickListener listener = mapboxMap.getOnMapClickListener(); - if (listener != null) { - LatLng point = projection.fromScreenLocation(tapPoint); - listener.onMapClick(point); - } - } - - trackGestureEvent(MapboxEvent.GESTURE_SINGLETAP, motionEvent.getX(), motionEvent.getY()); - return true; - } - - // Called for a long press - @Override - public void onLongPress(MotionEvent motionEvent) { - MapboxMap.OnMapLongClickListener listener = mapboxMap.getOnMapLongClickListener(); - if (listener != null && !quickZoom) { - LatLng point = projection.fromScreenLocation(new PointF(motionEvent.getX(), motionEvent.getY())); - listener.onMapLongClick(point); - } - } - - // Called for flings - @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { - if (destroyed || !mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) { - return false; - } - - mapboxMap.getTrackingSettings().resetTrackingModesIfRequired(true, false); - - double decelerationRate = 1; - - // Cancel any animation - mapboxMap.cancelTransitions(); - - double offsetX = velocityX * decelerationRate / 4 / screenDensity; - double offsetY = velocityY * decelerationRate / 4 / screenDensity; - - nativeMapView.setGestureInProgress(true); - nativeMapView.moveBy(offsetX, offsetY, (long) (decelerationRate * 1000.0f)); - nativeMapView.setGestureInProgress(false); - - MapboxMap.OnFlingListener listener = mapboxMap.getOnFlingListener(); - if (listener != null) { - listener.onFling(); - } - - trackGestureEvent(MapboxEvent.GESTURE_PAN_START, e1.getX(), e1.getY()); - return true; - } - - // Called for drags - @Override - public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { - if (!scrollInProgress) { - scrollInProgress = true; - } - if (destroyed || !mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) { - return false; - } - - if (dragStarted) { - return false; - } - - requestDisallowInterceptTouchEvent(true); - - // reset tracking if needed - mapboxMap.getTrackingSettings().resetTrackingModesIfRequired(true, false); - // Cancel any animation - mapboxMap.cancelTransitions(); - - // Scroll the map - nativeMapView.moveBy(-distanceX / screenDensity, -distanceY / screenDensity); - - MapboxMap.OnScrollListener listener = mapboxMap.getOnScrollListener(); - if (listener != null) { - listener.onScroll(); - } - return true; - } - } - - // This class handles two finger gestures and double-tap drag gestures - private class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { - - long beginTime = 0; - float scaleFactor = 1.0f; - - // Called when two fingers first touch the screen - @Override - public boolean onScaleBegin(ScaleGestureDetector detector) { - if (destroyed || !mapboxMap.getUiSettings().isZoomGesturesEnabled()) { - return false; - } - - beginTime = detector.getEventTime(); - trackGestureEvent(MapboxEvent.GESTURE_PINCH_START, detector.getFocusX(), detector.getFocusY()); - return true; - } - - // Called when fingers leave screen - @Override - public void onScaleEnd(ScaleGestureDetector detector) { - beginTime = 0; - scaleFactor = 1.0f; - zoomStarted = false; - } - - // Called each time a finger moves - // Called for pinch zooms and quickzooms/quickscales - @Override - public boolean onScale(ScaleGestureDetector detector) { - UiSettings uiSettings = mapboxMap.getUiSettings(); - if (destroyed || !uiSettings.isZoomGesturesEnabled()) { - return super.onScale(detector); - } - - // If scale is large enough ignore a tap - scaleFactor *= detector.getScaleFactor(); - if ((scaleFactor > 1.05f) || (scaleFactor < 0.95f)) { - zoomStarted = true; - } - - // Ignore short touches in case it is a tap - // Also ignore small scales - long time = detector.getEventTime(); - long interval = time - beginTime; - if (!zoomStarted && (interval <= ViewConfiguration.getTapTimeout())) { - return false; - } - - if (!zoomStarted) { - return false; - } - - if (dragStarted) { - return false; - } - - // Cancel any animation - mapboxMap.cancelTransitions(); - - // Gesture is a quickzoom if there aren't two fingers - quickZoom = !twoTap; - - // make an assumption here; if the zoom center is specified by the gesture, it's NOT going - // to be in the center of the map. Therefore the zoom will translate the map center, so tracking - // should be disabled. - - mapboxMap.getTrackingSettings().resetTrackingModesIfRequired(!quickZoom, false); - // Scale the map - if (focalPoint != null) { - // arround user provided focal point - nativeMapView.scaleBy(detector.getScaleFactor(), focalPoint.x / screenDensity, focalPoint.y / screenDensity); - } else if (quickZoom) { - // around center map - nativeMapView.scaleBy(detector.getScaleFactor(), (getWidth() / 2) / screenDensity, (getHeight() / 2) / screenDensity); - } else { - // around gesture - nativeMapView.scaleBy(detector.getScaleFactor(), detector.getFocusX() / screenDensity, detector.getFocusY() / screenDensity); - } - - return true; - } - } - - // This class handles two finger rotate gestures - private class RotateGestureListener extends RotateGestureDetector.SimpleOnRotateGestureListener { - - long beginTime = 0; - float totalAngle = 0.0f; - boolean started = false; - - // Called when two fingers first touch the screen - @Override - public boolean onRotateBegin(RotateGestureDetector detector) { - if (destroyed || !mapboxMap.getTrackingSettings().isRotateGestureCurrentlyEnabled()) { - return false; - } - - beginTime = detector.getEventTime(); - trackGestureEvent(MapboxEvent.GESTURE_ROTATION_START, detector.getFocusX(), detector.getFocusY()); - return true; - } - - // Called when the fingers leave the screen - @Override - public void onRotateEnd(RotateGestureDetector detector) { - beginTime = 0; - totalAngle = 0.0f; - started = false; - } - - // Called each time one of the two fingers moves - // Called for rotation - @Override - public boolean onRotate(RotateGestureDetector detector) { - if (destroyed || !mapboxMap.getTrackingSettings().isRotateGestureCurrentlyEnabled() || dragStarted) { - return false; - } - - // If rotate is large enough ignore a tap - // Also is zoom already started, don't rotate - totalAngle += detector.getRotationDegreesDelta(); - if (!zoomStarted && ((totalAngle > 20.0f) || (totalAngle < -20.0f))) { - started = true; - } - - // Ignore short touches in case it is a tap - // Also ignore small rotate - long time = detector.getEventTime(); - long interval = time - beginTime; - if (!started && (interval <= ViewConfiguration.getTapTimeout())) { - return false; - } - - if (!started) { - return false; - } - - // Cancel any animation - mapboxMap.cancelTransitions(); - - // rotation constitutes translation of anything except the center of - // rotation, so cancel both location and bearing tracking if required - - mapboxMap.getTrackingSettings().resetTrackingModesIfRequired(true, true); - - // Get rotate value - double bearing = nativeMapView.getBearing(); - bearing += detector.getRotationDegreesDelta(); - - // Rotate the map - if (focalPoint != null) { - // User provided focal point - setBearing(bearing, focalPoint.x / screenDensity, focalPoint.y / screenDensity); - } else { - // around gesture - setBearing(bearing, detector.getFocusX() / screenDensity, detector.getFocusY() / screenDensity); - } - return true; - } - } - - // This class handles a vertical two-finger shove. (If you place two fingers on screen with - // less than a 20 degree angle between them, this will detect movement on the Y-axis.) - private class ShoveGestureListener implements ShoveGestureDetector.OnShoveGestureListener { - - long beginTime = 0; - float totalDelta = 0.0f; - boolean started = false; - - @Override - public boolean onShoveBegin(ShoveGestureDetector detector) { - if (!mapboxMap.getUiSettings().isTiltGesturesEnabled()) { - return false; - } - - beginTime = detector.getEventTime(); - trackGestureEvent(MapboxEvent.GESTURE_PITCH_START, detector.getFocusX(), detector.getFocusY()); - return true; - } - - @Override - public void onShoveEnd(ShoveGestureDetector detector) { - beginTime = 0; - totalDelta = 0.0f; - started = false; - dragStarted = false; - } - - @Override - public boolean onShove(ShoveGestureDetector detector) { - if (destroyed || !mapboxMap.getUiSettings().isTiltGesturesEnabled()) { - return false; - } - - // If tilt is large enough ignore a tap - // Also if zoom already started, don't tilt - totalDelta += detector.getShovePixelsDelta(); - if (!zoomStarted && ((totalDelta > 10.0f) || (totalDelta < -10.0f))) { - started = true; - } - - // Ignore short touches in case it is a tap - // Also ignore small tilt - long time = detector.getEventTime(); - long interval = time - beginTime; - if (!started && (interval <= ViewConfiguration.getTapTimeout())) { - return false; - } - - if (!started) { - return false; - } - - // Cancel any animation - mapboxMap.cancelTransitions(); - - // Get tilt value (scale and clamp) - double pitch = getTilt(); - pitch -= 0.1 * detector.getShovePixelsDelta(); - pitch = Math.max(MapboxConstants.MINIMUM_TILT, Math.min(MapboxConstants.MAXIMUM_TILT, pitch)); - - // Tilt the map - mapboxMap.setTilt(pitch); - - dragStarted = true; - - return true; - } - } - - // This class handles input events from the zoom control buttons - // Zoom controls allow single touch only devices to zoom in and out - private class OnZoomListener implements ZoomButtonsController.OnZoomListener { - - // Not used - @Override - public void onVisibilityChanged(boolean visible) { - // Ignore - } - - // Called when user pushes a zoom button - @Override - public void onZoom(boolean zoomIn) { - if (!mapboxMap.getUiSettings().isZoomGesturesEnabled()) { - return; - } - zoom(zoomIn); - } - } - - // - // Input events - // - - // Called when the user presses a key, also called for repeating keys held - // down - @Override - public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) { - if (destroyed) { - return super.onKeyDown(keyCode, event); - } - - // If the user has held the scroll key down for a while then accelerate - // the scroll speed - double scrollDist = event.getRepeatCount() >= 5 ? 50.0 : 10.0; - - // Check which key was pressed via hardware/real key code - switch (keyCode) { - // Tell the system to track these keys for long presses on - // onKeyLongPress is fired - case KeyEvent.KEYCODE_ENTER: - case KeyEvent.KEYCODE_DPAD_CENTER: - event.startTracking(); - return true; - - case KeyEvent.KEYCODE_DPAD_LEFT: - if (!mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) { - return false; - } - - // Cancel any animation - mapboxMap.cancelTransitions(); - - // Move left - nativeMapView.moveBy(scrollDist / screenDensity, 0.0 / screenDensity); - return true; - - case KeyEvent.KEYCODE_DPAD_RIGHT: - if (!mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) { - return false; - } - - // Cancel any animation - mapboxMap.cancelTransitions(); - - // Move right - nativeMapView.moveBy(-scrollDist / screenDensity, 0.0 / screenDensity); - return true; - - case KeyEvent.KEYCODE_DPAD_UP: - if (!mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) { - return false; - } - - // Cancel any animation - mapboxMap.cancelTransitions(); - - // Move up - nativeMapView.moveBy(0.0 / screenDensity, scrollDist / screenDensity); - return true; - - case KeyEvent.KEYCODE_DPAD_DOWN: - if (!mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) { - return false; - } - - // Cancel any animation - mapboxMap.cancelTransitions(); - - // Move down - nativeMapView.moveBy(0.0 / screenDensity, -scrollDist / screenDensity); - return true; - - default: - // We are not interested in this key - return super.onKeyUp(keyCode, event); - } - } - - // Called when the user long presses a key that is being tracked - @Override - public boolean onKeyLongPress(int keyCode, KeyEvent event) { - // Check which key was pressed via hardware/real key code - switch (keyCode) { - // Tell the system to track these keys for long presses on - // onKeyLongPress is fired - case KeyEvent.KEYCODE_ENTER: - case KeyEvent.KEYCODE_DPAD_CENTER: - if (!mapboxMap.getUiSettings().isZoomGesturesEnabled()) { - return false; - } - - // Zoom out - zoom(false); - return true; - - default: - // We are not interested in this key - return super.onKeyUp(keyCode, event); - } - } - - // Called when the user releases a key - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - // Check if the key action was canceled (used for virtual keyboards) - if (event.isCanceled()) { - return super.onKeyUp(keyCode, event); - } - - // Check which key was pressed via hardware/real key code - // Note if keyboard does not have physical key (ie primary non-shifted - // key) then it will not appear here - // Must use the key character map as physical to character is not - // fixed/guaranteed - switch (keyCode) { - case KeyEvent.KEYCODE_ENTER: - case KeyEvent.KEYCODE_DPAD_CENTER: - if (!mapboxMap.getUiSettings().isZoomGesturesEnabled()) { - return false; - } - - // Zoom in - zoom(true); - return true; - } - - // We are not interested in this key - return super.onKeyUp(keyCode, event); - } - - // Called for trackball events, all motions are relative in device specific - // units - @Override - public boolean onTrackballEvent(MotionEvent event) { - if (destroyed) { - return false; - } - // Choose the action - switch (event.getActionMasked()) { - // The trackball was rotated - case MotionEvent.ACTION_MOVE: - if (!mapboxMap.getTrackingSettings().isScrollGestureCurrentlyEnabled()) { - return false; - } - - // Cancel any animation - mapboxMap.cancelTransitions(); - - // Scroll the map - nativeMapView.moveBy(-10.0 * event.getX() / screenDensity, -10.0 * event.getY() / screenDensity); - return true; - - // Trackball was pushed in so start tracking and tell system we are - // interested - // We will then get the up action - case MotionEvent.ACTION_DOWN: - // Set up a delayed callback to check if trackball is still - // After waiting the system long press time out - if (currentTrackballLongPressTimeOut != null) { - currentTrackballLongPressTimeOut.cancel(); - currentTrackballLongPressTimeOut = null; - } - currentTrackballLongPressTimeOut = new TrackballLongPressTimeOut(); - postDelayed(currentTrackballLongPressTimeOut, - ViewConfiguration.getLongPressTimeout()); - return true; - - // Trackball was released - case MotionEvent.ACTION_UP: - if (!mapboxMap.getUiSettings().isZoomGesturesEnabled()) { - return false; - } - - // Only handle if we have not already long pressed - if (currentTrackballLongPressTimeOut != null) { - // Zoom in - zoom(true); - } - return true; - - // Trackball was cancelled - case MotionEvent.ACTION_CANCEL: - if (currentTrackballLongPressTimeOut != null) { - currentTrackballLongPressTimeOut.cancel(); - currentTrackballLongPressTimeOut = null; - } - return true; - - default: - // We are not interested in this event - return super.onTrackballEvent(event); - } - } - - // This class implements the trackball long press time out callback - private class TrackballLongPressTimeOut implements Runnable { - - // Track if we have been cancelled - private boolean cancelled; - - TrackballLongPressTimeOut() { - cancelled = false; - } - - // Cancel the timeout - public void cancel() { - cancelled = true; - } - - // Called when long press time out expires - @Override - public void run() { - // Check if the trackball is still pressed - if (!cancelled) { - // Zoom out - zoom(false); - - // Ensure the up action is not run - currentTrackballLongPressTimeOut = null; - } - } - } - - // Called for events that don't fit the other handlers - // such as mouse scroll events, mouse moves, joystick, trackpad - @Override - public boolean onGenericMotionEvent(MotionEvent event) { - if (destroyed) { - return false; - } - // Mouse events - //if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { // this is not available before API 18 - if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == InputDevice.SOURCE_CLASS_POINTER) { - // Choose the action - switch (event.getActionMasked()) { - // Mouse scrolls - case MotionEvent.ACTION_SCROLL: - if (!mapboxMap.getUiSettings().isZoomGesturesEnabled()) { - return false; - } - - // Cancel any animation - mapboxMap.cancelTransitions(); - - // Get the vertical scroll amount, one click = 1 - float scrollDist = event.getAxisValue(MotionEvent.AXIS_VSCROLL); - - // Scale the map by the appropriate power of two factor - nativeMapView.scaleBy(Math.pow(2.0, scrollDist), event.getX() / screenDensity, event.getY() / screenDensity); - - return true; - - default: - // We are not interested in this event - return super.onGenericMotionEvent(event); - } - } - - // We are not interested in this event - return super.onGenericMotionEvent(event); - } - - // Called when the mouse pointer enters or exits the view - // or when it fades in or out due to movement - @Override - public boolean onHoverEvent(@NonNull MotionEvent event) { - switch (event.getActionMasked()) { - case MotionEvent.ACTION_HOVER_ENTER: - case MotionEvent.ACTION_HOVER_MOVE: - // Show the zoom controls - if (mapboxMap.getUiSettings().isZoomControlsEnabled()) { - zoomButtonsController.setVisible(true); - } - return true; - - case MotionEvent.ACTION_HOVER_EXIT: - // Hide the zoom controls - if (mapboxMap.getUiSettings().isZoomControlsEnabled()) { - zoomButtonsController.setVisible(false); - } - return true; - - default: - // We are not interested in this event - return super.onHoverEvent(event); + if (mapboxMap != null && mapboxMap.getUiSettings().isZoomControlsEnabled()) { + zoomButtonsController.setVisible(visibility == View.VISIBLE); } } @@ -2230,133 +907,6 @@ public class MapView extends FrameLayout { nativeMapView.onMapChangedEventDispatch(mapChange); } - // - // User location - // - - void setMyLocationEnabled(boolean enabled) { - myLocationView.setEnabled(enabled); - } - - Location getMyLocation() { - return myLocationView.getLocation(); - } - - void setOnMyLocationChangeListener(@Nullable final MapboxMap.OnMyLocationChangeListener listener) { - if (listener != null) { - myLocationListener = new LocationListener() { - @Override - public void onLocationChanged(Location location) { - if (listener != null) { - listener.onMyLocationChange(location); - } - } - }; - LocationServices.getLocationServices(getContext()).addLocationListener(myLocationListener); - } else { - LocationServices.getLocationServices(getContext()).removeLocationListener(myLocationListener); - myLocationListener = null; - } - } - - void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) { - if (myLocationTrackingMode != MyLocationTracking.TRACKING_NONE && !mapboxMap.isMyLocationEnabled()) { - mapboxMap.setMyLocationEnabled(true); - } - myLocationView.setMyLocationTrackingMode(myLocationTrackingMode); - - if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) { - setFocalPoint(new PointF(myLocationView.getCenterX(), myLocationView.getCenterY())); - } else { - setFocalPoint(null); - } - - MapboxMap.OnMyLocationTrackingModeChangeListener listener = mapboxMap.getOnMyLocationTrackingModeChangeListener(); - if (listener != null) { - listener.onMyLocationTrackingModeChange(myLocationTrackingMode); - } - } - - void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) { - if (myBearingTrackingMode != MyBearingTracking.NONE && !mapboxMap.isMyLocationEnabled()) { - mapboxMap.setMyLocationEnabled(true); - } - myLocationView.setMyBearingTrackingMode(myBearingTrackingMode); - MapboxMap.OnMyBearingTrackingModeChangeListener listener = mapboxMap.getOnMyBearingTrackingModeChangeListener(); - if (listener != null) { - listener.onMyBearingTrackingModeChange(myBearingTrackingMode); - } - } - - boolean isPermissionsAccepted() { - return (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) || - ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED; - } - - // - // Compass - // - - void setCompassEnabled(boolean compassEnabled) { - compassView.setEnabled(compassEnabled); - } - - void setCompassGravity(int gravity) { - setWidgetGravity(compassView, gravity); - } - - void setCompassMargins(int left, int top, int right, int bottom) { - setWidgetMargins(compassView, left, top, right, bottom); - } - - void setCompassFadeFacingNorth(boolean compassFadeFacingNorth) { - compassView.fadeCompassViewFacingNorth(compassFadeFacingNorth); - } - - // - // Logo - // - - void setLogoGravity(int gravity) { - setWidgetGravity(logoView, gravity); - } - - void setLogoMargins(int left, int top, int right, int bottom) { - setWidgetMargins(logoView, left, top, right, bottom); - } - - void setLogoEnabled(boolean visible) { - logoView.setVisibility(visible ? View.VISIBLE : View.GONE); - } - - // - // Attribution - // - - void setAttributionGravity(int gravity) { - setWidgetGravity(attributionsView, gravity); - } - - void setAttributionMargins(int left, int top, int right, int bottom) { - setWidgetMargins(attributionsView, left, top, right, bottom); - } - - void setAttributionEnabled(int visibility) { - attributionsView.setVisibility(visibility); - } - - void setAtttibutionTintColor(int tintColor) { - // Check that the tint color being passed in isn't transparent. - if (Color.alpha(tintColor) == 0) { - ColorUtils.setTintList(attributionsView, ContextCompat.getColor(getContext(), R.color.mapbox_blue)); - } else { - ColorUtils.setTintList(attributionsView, tintColor); - } - } - - int getAttributionTintColor() { - return mapboxMap.getUiSettings().getAttributionTintColor(); - } /** * Sets a callback object which will be triggered when the {@link MapboxMap} instance is ready to be used. @@ -2382,14 +932,6 @@ public class MapView extends FrameLayout { this.mapboxMap = mapboxMap; } - MyLocationView getUserLocationView() { - return myLocationView; - } - - NativeMapView getNativeMapView() { - return nativeMapView; - } - // // Snapshot API // @@ -2437,26 +979,6 @@ public class MapView extends FrameLayout { } } - // - // View utility methods - // - - private void setWidgetGravity(@NonNull final View view, int gravity) { - LayoutParams layoutParams = (LayoutParams) view.getLayoutParams(); - layoutParams.gravity = gravity; - view.setLayoutParams(layoutParams); - } - - private void setWidgetMargins(@NonNull final View view, int left, int top, int right, int bottom) { - LayoutParams layoutParams = (LayoutParams) view.getLayoutParams(); - left += contentPaddingLeft; - top += contentPaddingTop; - right += contentPaddingRight; - bottom += contentPaddingBottom; - layoutParams.setMargins(left, top, right, bottom); - view.setLayoutParams(layoutParams); - } - private static class AttributionOnClickListener implements View.OnClickListener, DialogInterface.OnClickListener { private static final int ATTRIBUTION_INDEX_IMPROVE_THIS_MAP = 2; @@ -2511,16 +1033,16 @@ public class MapView extends FrameLayout { } }); - AlertDialog telemDialog = builder.show(); - telemDialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(mapView.getAttributionTintColor()); - telemDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(mapView.getAttributionTintColor()); - telemDialog.getButton(AlertDialog.BUTTON_NEUTRAL).setTextColor(mapView.getAttributionTintColor()); + builder.show(); return; } String url = context.getResources().getStringArray(R.array.mapbox_attribution_links)[which]; if (which == ATTRIBUTION_INDEX_IMPROVE_THIS_MAP) { - LatLng latLng = mapView.getMapboxMap().getCameraPosition().target; - url = String.format(url, latLng.getLongitude(), latLng.getLatitude(), (int) mapView.getZoom()); + CameraPosition cameraPosition = mapView.getMapboxMap().getCameraPosition(); + if (cameraPosition != null) { + url = String.format(url, cameraPosition.target.getLongitude(), + cameraPosition.target.getLatitude(), (int) cameraPosition.zoom); + } } Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); @@ -2767,4 +1289,66 @@ public class MapView extends FrameLayout { void onMapChanged(@MapChange int change); } + // This class handles input events from the zoom control buttons + // Zoom controls allow single touch only devices to zoom in and out + private class OnZoomListener implements ZoomButtonsController.OnZoomListener { + + private UiSettings uiSettings; + private Transform transform; + + OnZoomListener(MapboxMap mapboxMap) { + this.uiSettings = mapboxMap.getUiSettings(); + this.transform = mapboxMap.getTransform(); + } + + // Not used + @Override + public void onVisibilityChanged(boolean visible) { + // Ignore + } + + // Called when user pushes a zoom button + @Override + public void onZoom(boolean zoomIn) { + if (!uiSettings.isZoomGesturesEnabled()) { + return; + } + transform.zoom(zoomIn); + } + } + + private class FocalPointInvalidator implements FocalPointChangeListener { + + @Override + public void onFocalPointChanged(PointF pointF) { + mapGestureDetector.setFocalPoint(pointF); + } + } + + private class RegisterTouchListener implements MapboxMap.OnRegisterTouchListener { + + @Override + public void onRegisterMapClickListener(MapboxMap.OnMapClickListener listener) { + mapGestureDetector.setOnMapClickListener(listener); + } + + @Override + public void onRegisterMapLongClickListener(MapboxMap.OnMapLongClickListener listener) { + mapGestureDetector.setOnMapLongClickListener(listener); + } + + @Override + public void onRegisterScrollListener(MapboxMap.OnScrollListener listener) { + mapGestureDetector.setOnScrollListener(listener); + } + + @Override + public void onRegisterFlingListener(MapboxMap.OnFlingListener listener) { + mapGestureDetector.setOnFlingListener(listener); + } + } + + NativeMapView getNativeMapView() { + return nativeMapView; + } } |