summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorŁukasz Paczos <lukas.paczos@gmail.com>2019-04-24 13:19:31 +0200
committerŁukasz Paczos <lukasz.paczos@mapbox.com>2019-04-24 14:24:23 +0200
commit50483cafa6fa4a2f5bc863020a0aad3d70ba2d0a (patch)
tree3b63605ddcb09b45579c8d56c52154fc0d15fff6
parenta67b3fc759d5a9ee0387d39719ed4b44f571c927 (diff)
downloadqtlocation-mapboxgl-50483cafa6fa4a2f5bc863020a0aad3d70ba2d0a.tar.gz
[android] clear up LocationComponent's z-index positioning docs and add "layer-above" option
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentOptions.java318
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentPositionManager.java48
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationLayerController.java33
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml5
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml1
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationComponentOptionsTest.java11
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationComponentPositionManagerTest.kt130
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.java3
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.kt3
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationModesActivity.java1
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/styles.xml2
11 files changed, 419 insertions, 136 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentOptions.java
index a7b83d7d9d..eb74cc7066 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentOptions.java
@@ -14,6 +14,7 @@ import android.support.annotation.StyleRes;
import com.mapbox.android.gestures.AndroidGesturesManager;
import com.mapbox.mapboxsdk.R;
+import com.mapbox.mapboxsdk.style.layers.Layer;
import java.util.Arrays;
@@ -108,6 +109,7 @@ public class LocationComponentOptions implements Parcelable {
private boolean trackingGesturesManagement;
private float trackingInitialMoveThreshold;
private float trackingMultiFingerMoveThreshold;
+ private String layerAbove;
private String layerBelow;
private float trackingAnimationDurationMultiplier;
private boolean compassAnimationEnabled;
@@ -142,6 +144,7 @@ public class LocationComponentOptions implements Parcelable {
boolean trackingGesturesManagement,
float trackingInitialMoveThreshold,
float trackingMultiFingerMoveThreshold,
+ String layerAbove,
String layerBelow,
float trackingAnimationDurationMultiplier,
boolean compassAnimationEnabled,
@@ -177,6 +180,7 @@ public class LocationComponentOptions implements Parcelable {
this.trackingGesturesManagement = trackingGesturesManagement;
this.trackingInitialMoveThreshold = trackingInitialMoveThreshold;
this.trackingMultiFingerMoveThreshold = trackingMultiFingerMoveThreshold;
+ this.layerAbove = layerAbove;
this.layerBelow = layerBelow;
this.trackingAnimationDurationMultiplier = trackingAnimationDurationMultiplier;
this.compassAnimationEnabled = compassAnimationEnabled;
@@ -271,6 +275,9 @@ public class LocationComponentOptions implements Parcelable {
typedArray.getInt(R.styleable.mapbox_LocationComponent_mapbox_iconPaddingBottom, 0),
});
+ builder.layerAbove(
+ typedArray.getString(R.styleable.mapbox_LocationComponent_mapbox_layer_above));
+
builder.layerBelow(
typedArray.getString(R.styleable.mapbox_LocationComponent_mapbox_layer_below));
@@ -681,9 +688,24 @@ public class LocationComponentOptions implements Parcelable {
}
/**
- * Gets the id of the layer to add the location component above to.
+ * Gets the id of the layer that's referenced when placing the component on the map using
+ * {@link com.mapbox.mapboxsdk.maps.Style#addLayerAbove(Layer, String)}.
+ * <p>
+ * The component is going to placed directly above this layer.
+ *
+ * @return layerAbove the id of the layer the component is going to placed directly above.
+ */
+ public String layerAbove() {
+ return layerAbove;
+ }
+
+ /**
+ * Gets the id of the layer that's referenced when placing the component on the map using
+ * {@link com.mapbox.mapboxsdk.maps.Style#addLayerBelow(Layer, String)}.
+ * <p>
+ * The component is going to placed directly below this layer.
*
- * @return layerBelow the id of the layer to add the location component above to
+ * @return layerBelow the id of the layer the component is going to placed directly below.
*/
public String layerBelow() {
return layerBelow;
@@ -749,6 +771,7 @@ public class LocationComponentOptions implements Parcelable {
+ "trackingGesturesManagement=" + trackingGesturesManagement + ", "
+ "trackingInitialMoveThreshold=" + trackingInitialMoveThreshold + ", "
+ "trackingMultiFingerMoveThreshold=" + trackingMultiFingerMoveThreshold + ", "
+ + "layerAbove=" + layerAbove
+ "layerBelow=" + layerBelow
+ "trackingAnimationDurationMultiplier=" + trackingAnimationDurationMultiplier
+ "}";
@@ -756,124 +779,160 @@ public class LocationComponentOptions implements Parcelable {
@Override
public boolean equals(Object o) {
- if (o == this) {
+ if (this == o) {
return true;
}
- if (o instanceof LocationComponentOptions) {
- LocationComponentOptions that = (LocationComponentOptions) o;
- return (Float.floatToIntBits(this.accuracyAlpha) == Float.floatToIntBits(that.accuracyAlpha()))
- && (this.accuracyColor == that.accuracyColor())
- && (this.backgroundDrawableStale == that.backgroundDrawableStale())
- && ((this.backgroundStaleName == null) ? (that.backgroundStaleName() == null)
- : this.backgroundStaleName.equals(that.backgroundStaleName()))
- && (this.foregroundDrawableStale == that.foregroundDrawableStale())
- && ((this.foregroundStaleName == null) ? (that.foregroundStaleName() == null)
- : this.foregroundStaleName.equals(that.foregroundStaleName()))
- && (this.gpsDrawable == that.gpsDrawable())
- && ((this.gpsName == null) ? (that.gpsName() == null) : this.gpsName.equals(that.gpsName()))
- && (this.foregroundDrawable == that.foregroundDrawable())
- && ((this.foregroundName == null) ? (that.foregroundName() == null)
- : this.foregroundName.equals(that.foregroundName()))
- && (this.backgroundDrawable == that.backgroundDrawable())
- && ((this.backgroundName == null) ? (that.backgroundName() == null)
- : this.backgroundName.equals(that.backgroundName()))
- && (this.bearingDrawable == that.bearingDrawable())
- && ((this.bearingName == null) ? (that.bearingName() == null)
- : this.bearingName.equals(that.bearingName()))
- && ((this.bearingTintColor == null) ? (that.bearingTintColor() == null)
- : this.bearingTintColor.equals(that.bearingTintColor()))
- && ((this.foregroundTintColor == null) ? (that.foregroundTintColor() == null)
- : this.foregroundTintColor.equals(that.foregroundTintColor()))
- && ((this.backgroundTintColor == null) ? (that.backgroundTintColor() == null)
- : this.backgroundTintColor.equals(that.backgroundTintColor()))
- && ((this.foregroundStaleTintColor == null) ? (that.foregroundStaleTintColor() == null)
- : this.foregroundStaleTintColor.equals(that.foregroundStaleTintColor()))
- && ((this.backgroundStaleTintColor == null) ? (that.backgroundStaleTintColor() == null)
- : this.backgroundStaleTintColor.equals(that.backgroundStaleTintColor()))
- && (Float.floatToIntBits(this.elevation) == Float.floatToIntBits(that.elevation()))
- && (this.enableStaleState == that.enableStaleState())
- && (this.staleStateTimeout == that.staleStateTimeout())
- && (Arrays.equals(this.padding, that.padding())
- && (Float.floatToIntBits(this.maxZoomIconScale) == Float.floatToIntBits(that.maxZoomIconScale()))
- && (Float.floatToIntBits(this.minZoomIconScale) == Float.floatToIntBits(that.minZoomIconScale()))
- && (this.trackingGesturesManagement == that.trackingGesturesManagement())
- && (Float.floatToIntBits(this.trackingInitialMoveThreshold)
- == Float.floatToIntBits(that.trackingInitialMoveThreshold()))
- && (Float.floatToIntBits(this.trackingMultiFingerMoveThreshold)
- == Float.floatToIntBits(that.trackingMultiFingerMoveThreshold()))
- && layerBelow.equals(that.layerBelow))
- && (Float.floatToIntBits(this.trackingAnimationDurationMultiplier)
- == Float.floatToIntBits(that.trackingAnimationDurationMultiplier()));
- }
- return false;
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ LocationComponentOptions options = (LocationComponentOptions) o;
+
+ if (Float.compare(options.accuracyAlpha, accuracyAlpha) != 0) {
+ return false;
+ }
+ if (accuracyColor != options.accuracyColor) {
+ return false;
+ }
+ if (backgroundDrawableStale != options.backgroundDrawableStale) {
+ return false;
+ }
+ if (foregroundDrawableStale != options.foregroundDrawableStale) {
+ return false;
+ }
+ if (gpsDrawable != options.gpsDrawable) {
+ return false;
+ }
+ if (foregroundDrawable != options.foregroundDrawable) {
+ return false;
+ }
+ if (backgroundDrawable != options.backgroundDrawable) {
+ return false;
+ }
+ if (bearingDrawable != options.bearingDrawable) {
+ return false;
+ }
+ if (Float.compare(options.elevation, elevation) != 0) {
+ return false;
+ }
+ if (enableStaleState != options.enableStaleState) {
+ return false;
+ }
+ if (staleStateTimeout != options.staleStateTimeout) {
+ return false;
+ }
+ if (Float.compare(options.maxZoomIconScale, maxZoomIconScale) != 0) {
+ return false;
+ }
+ if (Float.compare(options.minZoomIconScale, minZoomIconScale) != 0) {
+ return false;
+ }
+ if (trackingGesturesManagement != options.trackingGesturesManagement) {
+ return false;
+ }
+ if (Float.compare(options.trackingInitialMoveThreshold, trackingInitialMoveThreshold) != 0) {
+ return false;
+ }
+ if (Float.compare(options.trackingMultiFingerMoveThreshold, trackingMultiFingerMoveThreshold) != 0) {
+ return false;
+ }
+ if (Float.compare(options.trackingAnimationDurationMultiplier, trackingAnimationDurationMultiplier) != 0) {
+ return false;
+ }
+ if (compassAnimationEnabled != options.compassAnimationEnabled) {
+ return false;
+ }
+ if (accuracyAnimationEnabled != options.accuracyAnimationEnabled) {
+ return false;
+ }
+ if (backgroundStaleName != null ? !backgroundStaleName.equals(options.backgroundStaleName) :
+ options.backgroundStaleName != null) {
+ return false;
+ }
+ if (foregroundStaleName != null ? !foregroundStaleName.equals(options.foregroundStaleName) :
+ options.foregroundStaleName != null) {
+ return false;
+ }
+ if (gpsName != null ? !gpsName.equals(options.gpsName) : options.gpsName != null) {
+ return false;
+ }
+ if (foregroundName != null ? !foregroundName.equals(options.foregroundName) : options.foregroundName != null) {
+ return false;
+ }
+ if (backgroundName != null ? !backgroundName.equals(options.backgroundName) : options.backgroundName != null) {
+ return false;
+ }
+ if (bearingName != null ? !bearingName.equals(options.bearingName) : options.bearingName != null) {
+ return false;
+ }
+ if (bearingTintColor != null ? !bearingTintColor.equals(options.bearingTintColor) :
+ options.bearingTintColor != null) {
+ return false;
+ }
+ if (foregroundTintColor != null ? !foregroundTintColor.equals(options.foregroundTintColor) :
+ options.foregroundTintColor != null) {
+ return false;
+ }
+ if (backgroundTintColor != null ? !backgroundTintColor.equals(options.backgroundTintColor) :
+ options.backgroundTintColor != null) {
+ return false;
+ }
+ if (foregroundStaleTintColor != null ? !foregroundStaleTintColor.equals(options.foregroundStaleTintColor) :
+ options.foregroundStaleTintColor != null) {
+ return false;
+ }
+ if (backgroundStaleTintColor != null ? !backgroundStaleTintColor.equals(options.backgroundStaleTintColor) :
+ options.backgroundStaleTintColor != null) {
+ return false;
+ }
+ if (!Arrays.equals(padding, options.padding)) {
+ return false;
+ }
+ if (layerAbove != null ? !layerAbove.equals(options.layerAbove) : options.layerAbove != null) {
+ return false;
+ }
+ return layerBelow != null ? layerBelow.equals(options.layerBelow) : options.layerBelow == null;
}
@Override
public int hashCode() {
- int h$ = 1;
- h$ *= 1000003;
- h$ ^= Float.floatToIntBits(accuracyAlpha);
- h$ *= 1000003;
- h$ ^= accuracyColor;
- h$ *= 1000003;
- h$ ^= backgroundDrawableStale;
- h$ *= 1000003;
- h$ ^= (backgroundStaleName == null) ? 0 : backgroundStaleName.hashCode();
- h$ *= 1000003;
- h$ ^= foregroundDrawableStale;
- h$ *= 1000003;
- h$ ^= (foregroundStaleName == null) ? 0 : foregroundStaleName.hashCode();
- h$ *= 1000003;
- h$ ^= gpsDrawable;
- h$ *= 1000003;
- h$ ^= (gpsName == null) ? 0 : gpsName.hashCode();
- h$ *= 1000003;
- h$ ^= foregroundDrawable;
- h$ *= 1000003;
- h$ ^= (foregroundName == null) ? 0 : foregroundName.hashCode();
- h$ *= 1000003;
- h$ ^= backgroundDrawable;
- h$ *= 1000003;
- h$ ^= (backgroundName == null) ? 0 : backgroundName.hashCode();
- h$ *= 1000003;
- h$ ^= bearingDrawable;
- h$ *= 1000003;
- h$ ^= (bearingName == null) ? 0 : bearingName.hashCode();
- h$ *= 1000003;
- h$ ^= (bearingTintColor == null) ? 0 : bearingTintColor.hashCode();
- h$ *= 1000003;
- h$ ^= (foregroundTintColor == null) ? 0 : foregroundTintColor.hashCode();
- h$ *= 1000003;
- h$ ^= (backgroundTintColor == null) ? 0 : backgroundTintColor.hashCode();
- h$ *= 1000003;
- h$ ^= (foregroundStaleTintColor == null) ? 0 : foregroundStaleTintColor.hashCode();
- h$ *= 1000003;
- h$ ^= (backgroundStaleTintColor == null) ? 0 : backgroundStaleTintColor.hashCode();
- h$ *= 1000003;
- h$ ^= Float.floatToIntBits(elevation);
- h$ *= 1000003;
- h$ ^= enableStaleState ? 1231 : 1237;
- h$ *= 1000003;
- h$ ^= (int) ((staleStateTimeout >>> 32) ^ staleStateTimeout);
- h$ *= 1000003;
- h$ ^= Arrays.hashCode(padding);
- h$ *= 1000003;
- h$ ^= Float.floatToIntBits(maxZoomIconScale);
- h$ *= 1000003;
- h$ ^= Float.floatToIntBits(minZoomIconScale);
- h$ *= 1000003;
- h$ ^= trackingGesturesManagement ? 1231 : 1237;
- h$ *= 1000003;
- h$ ^= Float.floatToIntBits(trackingInitialMoveThreshold);
- h$ *= 1000003;
- h$ ^= Float.floatToIntBits(trackingMultiFingerMoveThreshold);
- h$ *= 1000003;
- h$ ^= Float.floatToIntBits(trackingAnimationDurationMultiplier);
- h$ *= 1000003;
- h$ ^= compassAnimationEnabled ? 1231 : 1237;
- h$ *= 1000003;
- h$ ^= accuracyAnimationEnabled ? 1231 : 1237;
- return h$;
+ int result = (accuracyAlpha != +0.0f ? Float.floatToIntBits(accuracyAlpha) : 0);
+ result = 31 * result + accuracyColor;
+ result = 31 * result + backgroundDrawableStale;
+ result = 31 * result + (backgroundStaleName != null ? backgroundStaleName.hashCode() : 0);
+ result = 31 * result + foregroundDrawableStale;
+ result = 31 * result + (foregroundStaleName != null ? foregroundStaleName.hashCode() : 0);
+ result = 31 * result + gpsDrawable;
+ result = 31 * result + (gpsName != null ? gpsName.hashCode() : 0);
+ result = 31 * result + foregroundDrawable;
+ result = 31 * result + (foregroundName != null ? foregroundName.hashCode() : 0);
+ result = 31 * result + backgroundDrawable;
+ result = 31 * result + (backgroundName != null ? backgroundName.hashCode() : 0);
+ result = 31 * result + bearingDrawable;
+ result = 31 * result + (bearingName != null ? bearingName.hashCode() : 0);
+ result = 31 * result + (bearingTintColor != null ? bearingTintColor.hashCode() : 0);
+ result = 31 * result + (foregroundTintColor != null ? foregroundTintColor.hashCode() : 0);
+ result = 31 * result + (backgroundTintColor != null ? backgroundTintColor.hashCode() : 0);
+ result = 31 * result + (foregroundStaleTintColor != null ? foregroundStaleTintColor.hashCode() : 0);
+ result = 31 * result + (backgroundStaleTintColor != null ? backgroundStaleTintColor.hashCode() : 0);
+ result = 31 * result + (elevation != +0.0f ? Float.floatToIntBits(elevation) : 0);
+ result = 31 * result + (enableStaleState ? 1 : 0);
+ result = 31 * result + (int) (staleStateTimeout ^ (staleStateTimeout >>> 32));
+ result = 31 * result + Arrays.hashCode(padding);
+ result = 31 * result + (maxZoomIconScale != +0.0f ? Float.floatToIntBits(maxZoomIconScale) : 0);
+ result = 31 * result + (minZoomIconScale != +0.0f ? Float.floatToIntBits(minZoomIconScale) : 0);
+ result = 31 * result + (trackingGesturesManagement ? 1 : 0);
+ result = 31 * result + (trackingInitialMoveThreshold != +0.0f
+ ? Float.floatToIntBits(trackingInitialMoveThreshold) : 0);
+ result = 31 * result + (trackingMultiFingerMoveThreshold != +0.0f
+ ? Float.floatToIntBits(trackingMultiFingerMoveThreshold) : 0);
+ result = 31 * result + (layerAbove != null ? layerAbove.hashCode() : 0);
+ result = 31 * result + (layerBelow != null ? layerBelow.hashCode() : 0);
+ result = 31 * result + (trackingAnimationDurationMultiplier != +0.0f
+ ? Float.floatToIntBits(trackingAnimationDurationMultiplier) : 0);
+ result = 31 * result + (compassAnimationEnabled ? 1 : 0);
+ result = 31 * result + (accuracyAnimationEnabled ? 1 : 0);
+ return result;
}
public static final Parcelable.Creator<LocationComponentOptions> CREATOR =
@@ -910,6 +969,7 @@ public class LocationComponentOptions implements Parcelable {
in.readFloat(),
in.readFloat(),
in.readString(),
+ in.readString(),
in.readFloat(),
in.readInt() == 1,
in.readInt() == 1
@@ -1007,6 +1067,7 @@ public class LocationComponentOptions implements Parcelable {
dest.writeInt(trackingGesturesManagement() ? 1 : 0);
dest.writeFloat(trackingInitialMoveThreshold());
dest.writeFloat(trackingMultiFingerMoveThreshold());
+ dest.writeString(layerAbove());
dest.writeString(layerBelow());
dest.writeFloat(trackingAnimationDurationMultiplier);
dest.writeInt(compassAnimationEnabled() ? 1 : 0);
@@ -1041,6 +1102,11 @@ public class LocationComponentOptions implements Parcelable {
+ locationComponentOptions.elevation() + ". Must be >= 0");
}
+ if (locationComponentOptions.layerAbove() != null && locationComponentOptions.layerBelow() != null) {
+ throw new IllegalArgumentException("You cannot set both layerAbove and layerBelow options."
+ + "Choose one or the other.");
+ }
+
return locationComponentOptions;
}
@@ -1084,6 +1150,7 @@ public class LocationComponentOptions implements Parcelable {
private Boolean trackingGesturesManagement;
private Float trackingInitialMoveThreshold;
private Float trackingMultiFingerMoveThreshold;
+ private String layerAbove;
private String layerBelow;
private Float trackingAnimationDurationMultiplier;
private Boolean compassAnimationEnabled;
@@ -1121,6 +1188,7 @@ public class LocationComponentOptions implements Parcelable {
this.trackingGesturesManagement = source.trackingGesturesManagement();
this.trackingInitialMoveThreshold = source.trackingInitialMoveThreshold();
this.trackingMultiFingerMoveThreshold = source.trackingMultiFingerMoveThreshold();
+ this.layerAbove = source.layerAbove();
this.layerBelow = source.layerBelow();
this.trackingAnimationDurationMultiplier = source.trackingAnimationDurationMultiplier();
this.compassAnimationEnabled = source.compassAnimationEnabled();
@@ -1547,9 +1615,26 @@ public class LocationComponentOptions implements Parcelable {
}
/**
- * Sets the layer id to set the location component below to.
+ * Sets the id of the layer that's referenced when placing the component on the map using
+ * {@link com.mapbox.mapboxsdk.maps.Style#addLayerAbove(Layer, String)}.
+ * <p>
+ * The component is going to placed directly above this layer.
+ *
+ * @param layerAbove the id of the layer the component is going to placed directly above.
+ */
+ @NonNull
+ public LocationComponentOptions.Builder layerAbove(String layerAbove) {
+ this.layerAbove = layerAbove;
+ return this;
+ }
+
+ /**
+ * Sets the id of the layer that's referenced when placing the component on the map using
+ * {@link com.mapbox.mapboxsdk.maps.Style#addLayerBelow(Layer, String)}.
+ * <p>
+ * The component is going to placed directly below this layer.
*
- * @param layerBelow the id to set the location component below to.
+ * @param layerBelow the id of the layer the component is going to placed directly below.
*/
@NonNull
public LocationComponentOptions.Builder layerBelow(String layerBelow) {
@@ -1679,6 +1764,7 @@ public class LocationComponentOptions implements Parcelable {
trackingGesturesManagement,
this.trackingInitialMoveThreshold,
this.trackingMultiFingerMoveThreshold,
+ this.layerAbove,
this.layerBelow,
this.trackingAnimationDurationMultiplier,
this.compassAnimationEnabled,
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentPositionManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentPositionManager.java
new file mode 100644
index 0000000000..f2e4d0bb41
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationComponentPositionManager.java
@@ -0,0 +1,48 @@
+package com.mapbox.mapboxsdk.location;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import com.mapbox.mapboxsdk.maps.Style;
+import com.mapbox.mapboxsdk.style.layers.Layer;
+
+class LocationComponentPositionManager {
+
+ @NonNull
+ private final Style style;
+
+ @Nullable
+ private String layerAbove;
+
+ @Nullable
+ private String layerBelow;
+
+ LocationComponentPositionManager(@NonNull Style style, @Nullable String layerAbove, @Nullable String layerBelow) {
+ this.style = style;
+ this.layerAbove = layerAbove;
+ this.layerBelow = layerBelow;
+ }
+
+ /**
+ * Returns true whenever layer above/below configuration has changed and requires re-layout.
+ */
+ boolean update(@Nullable String layerAbove, @Nullable String layerBelow) {
+ boolean requiresUpdate =
+ !(this.layerAbove == layerAbove || (this.layerAbove != null && this.layerAbove.equals(layerAbove)))
+ || !(this.layerBelow == layerBelow || (this.layerBelow != null && this.layerBelow.equals(layerBelow)));
+
+ this.layerAbove = layerAbove;
+ this.layerBelow = layerBelow;
+ return requiresUpdate;
+ }
+
+ void addLayerToMap(@NonNull Layer layer) {
+ if (layerAbove != null) {
+ style.addLayerAbove(layer, layerAbove);
+ } else if (layerBelow != null) {
+ style.addLayerBelow(layer, layerBelow);
+ } else {
+ style.addLayer(layer);
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationLayerController.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationLayerController.java
index aa8a82bf6d..c0c6017cd6 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationLayerController.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationLayerController.java
@@ -77,8 +77,7 @@ final class LocationLayerController {
private boolean isHidden = true;
- @Nullable
- private String layerBelow;
+ private LocationComponentPositionManager positionManager;
LocationLayerController(MapboxMap mapboxMap, Style style, LayerSourceProvider layerSourceProvider,
LayerFeatureProvider featureProvider, LayerBitmapProvider bitmapProvider,
@@ -95,8 +94,9 @@ final class LocationLayerController {
void initializeComponents(Style style, LocationComponentOptions options) {
this.style = style;
+ this.positionManager = new LocationComponentPositionManager(style, options.layerAbove(), options.layerBelow());
addLocationSource();
- addLayers(options.layerBelow());
+ addLayers();
applyStyle(options);
if (isHidden) {
@@ -107,18 +107,15 @@ final class LocationLayerController {
}
void applyStyle(@NonNull LocationComponentOptions options) {
- String newLayerBelowOption = options.layerBelow();
- if ((layerBelow != null || newLayerBelowOption != null)) {
- if (layerBelow == null || !layerBelow.equals(newLayerBelowOption)) {
- removeLayers();
- addLayers(newLayerBelowOption);
- if (isHidden) {
- for (String layerId : layerSet) {
- setLayerVisibility(layerId, false);
- }
+ if (positionManager.update(options.layerAbove(), options.layerBelow())) {
+ removeLayers();
+ addLayers();
+ if (isHidden) {
+ for (String layerId : layerSet) {
+ setLayerVisibility(layerId, false);
}
- setRenderMode(renderMode);
}
+ setRenderMode(renderMode);
}
this.options = options;
@@ -237,9 +234,13 @@ final class LocationLayerController {
}
}
- private void addLayers(@NonNull String idBelowLayer) {
- layerBelow = idBelowLayer;
- addSymbolLayer(BEARING_LAYER, idBelowLayer);
+ private void addLayers() {
+ // positions the top-most reference layer
+ Layer layer = layerSourceProvider.generateLayer(BEARING_LAYER);
+ positionManager.addLayerToMap(layer);
+ layerSet.add(layer.getId());
+
+ // adds remaining layers while keeping the order
addSymbolLayer(FOREGROUND_LAYER, BEARING_LAYER);
addSymbolLayer(BACKGROUND_LAYER, FOREGROUND_LAYER);
addSymbolLayer(SHADOW_LAYER, BACKGROUND_LAYER);
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml b/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml
index 58109257f2..756b337f12 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml
@@ -150,4 +150,9 @@
<!-- Accuracy animation-->
<public name="mapbox_accuracyAnimationEnabled" format="boolean" type="attr" />
+
+ <!--LocationComponent position-->
+ <public name="mapbox_layer_above" format="string" type="attr" />
+ <public name="mapbox_layer_below" format="string" type="attr" />
+
</resources>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml
index 2eeb5057f2..a7182d6e4b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml
@@ -156,6 +156,7 @@
<attr name="mapbox_iconPaddingBottom" format="integer"/>
<!-- Map layer configuration -->
+ <attr name="mapbox_layer_above" format="string"/>
<attr name="mapbox_layer_below" format="string"/>
<!-- Icon scale based on map zoom levels -->
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationComponentOptionsTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationComponentOptionsTest.java
index f228adcce7..b1e1f14cb1 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationComponentOptionsTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationComponentOptionsTest.java
@@ -67,4 +67,15 @@ public class LocationComponentOptionsTest {
.elevation(-500)
.build();
}
+
+ @Test
+ public void passingBothLayerPositionOptions_throwsException() throws Exception {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("You cannot set both layerAbove and layerBelow options."
+ + "Choose one or the other.");
+ LocationComponentOptions.builder(context)
+ .layerAbove("above")
+ .layerBelow("below")
+ .build();
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationComponentPositionManagerTest.kt b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationComponentPositionManagerTest.kt
new file mode 100644
index 0000000000..c8a75b6701
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationComponentPositionManagerTest.kt
@@ -0,0 +1,130 @@
+package com.mapbox.mapboxsdk.location
+
+import com.mapbox.mapboxsdk.maps.Style
+import com.mapbox.mapboxsdk.style.layers.Layer
+import io.mockk.mockk
+import io.mockk.verify
+import junit.framework.Assert.assertFalse
+import junit.framework.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.junit.MockitoJUnitRunner
+
+@RunWith(MockitoJUnitRunner::class)
+class LocationComponentPositionManagerTest {
+
+ private lateinit var style: Style
+ private lateinit var layer: Layer
+
+ @Before
+ fun setup() {
+ style = mockk(relaxed = true)
+ layer = mockk(relaxed = true)
+ }
+
+ @Test
+ fun update_noChange_null() {
+ val positionManager = LocationComponentPositionManager(style, null, null)
+ val requiresUpdate = positionManager.update(null, null)
+ assertFalse(requiresUpdate)
+ }
+
+ @Test
+ fun update_noChange_above() {
+ val positionManager = LocationComponentPositionManager(style, "above", null)
+ val requiresUpdate = positionManager.update("above", null)
+ assertFalse(requiresUpdate)
+ }
+
+ @Test
+ fun update_noChange_below() {
+ val positionManager = LocationComponentPositionManager(style, null, "below")
+ val requiresUpdate = positionManager.update(null, "below")
+ assertFalse(requiresUpdate)
+ }
+
+ @Test
+ fun update_fromNull_above() {
+ val positionManager = LocationComponentPositionManager(style, null, null)
+ val requiresUpdate = positionManager.update("above", null)
+ assertTrue(requiresUpdate)
+ }
+
+ @Test
+ fun update_fromNull_below() {
+ val positionManager = LocationComponentPositionManager(style, null, null)
+ val requiresUpdate = positionManager.update(null, "below")
+ assertTrue(requiresUpdate)
+ }
+
+ @Test
+ fun update_toNull_above() {
+ val positionManager = LocationComponentPositionManager(style, "above", null)
+ val requiresUpdate = positionManager.update(null, null)
+ assertTrue(requiresUpdate)
+ }
+
+ @Test
+ fun update_toNull_below() {
+ val positionManager = LocationComponentPositionManager(style, null, "below")
+ val requiresUpdate = positionManager.update(null, null)
+ assertTrue(requiresUpdate)
+ }
+
+ @Test
+ fun update_fromValue_above() {
+ val positionManager = LocationComponentPositionManager(style, "above1", null)
+ val requiresUpdate = positionManager.update("above2", null)
+ assertTrue(requiresUpdate)
+ }
+
+ @Test
+ fun update_fromValue_below() {
+ val positionManager = LocationComponentPositionManager(style, null, "below1")
+ val requiresUpdate = positionManager.update(null, "below2")
+ assertTrue(requiresUpdate)
+ }
+
+ @Test
+ fun addLayer_noModifier() {
+ val positionManager = LocationComponentPositionManager(style, null, null)
+ positionManager.addLayerToMap(layer)
+
+ verify { style.addLayer(layer) }
+ }
+
+ @Test
+ fun addLayer_above() {
+ val positionManager = LocationComponentPositionManager(style, "above", null)
+ positionManager.addLayerToMap(layer)
+
+ verify { style.addLayerAbove(layer, "above") }
+ }
+
+ @Test
+ fun addLayer_below() {
+ val positionManager = LocationComponentPositionManager(style, null, "below")
+ positionManager.addLayerToMap(layer)
+
+ verify { style.addLayerBelow(layer, "below") }
+ }
+
+ @Test
+ fun addLayer_afterUpdate_above() {
+ val positionManager = LocationComponentPositionManager(style, null, null)
+ positionManager.update("above", null)
+ positionManager.addLayerToMap(layer)
+
+ verify { style.addLayerAbove(layer, "above") }
+ }
+
+ @Test
+ fun addLayer_afterUpdate_below() {
+ val positionManager = LocationComponentPositionManager(style, null, null)
+ positionManager.update(null, "below")
+ positionManager.addLayerToMap(layer)
+
+ verify { style.addLayerBelow(layer, "below") }
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.java
index 6a44cf1f79..aa0a07b73e 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.java
@@ -400,7 +400,8 @@ public class LocationLayerControllerTest {
layerController.applyStyle(options);
verify(style, times(0)).removeLayer(any(String.class));
- verify(style, times(5)).addLayerBelow(any(Layer.class), Mockito.<String>any());
+ verify(style, times(1)).addLayer(any(Layer.class));
+ verify(style, times(4)).addLayerBelow(any(Layer.class), Mockito.<String>any());
}
@Test
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.kt
index fb450de527..95a3891b6d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.kt
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/location/LocationLayerControllerTest.kt
@@ -284,8 +284,7 @@ class LocationLayerControllerTest : EspressoTest() {
TestingAsyncUtils.waitForLayer(uiController, mapView)
assertThat(mapboxMap.queryRenderedFeatures(location, FOREGROUND_LAYER).isEmpty(), `is`(true))
- val options =
- LocationComponentOptions.createFromAttributes(context, com.mapbox.mapboxsdk.testapp.R.style.CustomLocationComponent)
+ val options = component.locationComponentOptions
.toBuilder()
.layerBelow("road-label")
.build()
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationModesActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationModesActivity.java
index 28d165428d..718a536a08 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationModesActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/location/LocationModesActivity.java
@@ -207,7 +207,6 @@ public class LocationModesActivity extends AppCompatActivity implements OnMapRea
options = options.toBuilder()
.padding(padding)
- .layerBelow("road-label")
.build();
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/styles.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/styles.xml
index faa994e978..8d7da603f7 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/styles.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/styles.xml
@@ -50,6 +50,8 @@
<item name="mapbox_elevation">0dp</item>
<item name="mapbox_compassAnimationEnabled">false</item>
<item name="mapbox_accuracyAnimationEnabled">false</item>
+
+ <item name="mapbox_layer_above">road-label</item>
</style>
</resources>