diff --git a/MapboxAndroidDemo/src/global/java/com/mapbox/mapboxandroiddemo/MainActivity.java b/MapboxAndroidDemo/src/global/java/com/mapbox/mapboxandroiddemo/MainActivity.java
index 7f7d31729..fa9721f4a 100644
--- a/MapboxAndroidDemo/src/global/java/com/mapbox/mapboxandroiddemo/MainActivity.java
+++ b/MapboxAndroidDemo/src/global/java/com/mapbox/mapboxandroiddemo/MainActivity.java
@@ -33,6 +33,7 @@
import com.mapbox.mapboxandroiddemo.examples.camera.RestrictCameraActivity;
import com.mapbox.mapboxandroiddemo.examples.camera.SlowlyRotatingCameraActivity;
import com.mapbox.mapboxandroiddemo.examples.dds.AddRainFallStyleActivity;
+import com.mapbox.mapboxandroiddemo.examples.dds.AnimatedDashLineActivity;
import com.mapbox.mapboxandroiddemo.examples.dds.BathymetryActivity;
import com.mapbox.mapboxandroiddemo.examples.dds.ChoroplethJsonVectorMixActivity;
import com.mapbox.mapboxandroiddemo.examples.dds.ChoroplethZoomChangeActivity;
@@ -604,6 +605,15 @@ private void initializeModels() {
null,
R.string.activity_style_image_source_url, false, BuildConfig.MIN_SDK_VERSION
));
+ exampleItemModels.add(new ExampleItemModel(
+ R.id.nav_styles,
+ R.string.activity_styles_click_to_add_image_title,
+ R.string.activity_styles_click_to_add_image_description,
+ new Intent(MainActivity.this, ClickToAddImageActivity.class),
+ null,
+ R.string.activity_styles_click_to_add_image_url, false, BuildConfig.MIN_SDK_VERSION
+ ));
+
exampleItemModels.add(new ExampleItemModel(
R.id.nav_styles,
R.string.activity_style_image_source_time_lapse_title,
@@ -1474,6 +1484,22 @@ private void initializeModels() {
null,
R.string.activity_dds_polygon_revealed_hole_outline_url, false, BuildConfig.MIN_SDK_VERSION));
+ exampleItemModels.add(new ExampleItemModel(
+ R.id.nav_dds,
+ R.string.activity_dashed_line_directions_picker_title,
+ R.string.activity_dashed_line_directions_picker_description,
+ new Intent(MainActivity.this, DashedLineDirectionsPickerActivity.class),
+ null,
+ R.string.activity_dashed_line_directions_picker_url, true, BuildConfig.MIN_SDK_VERSION));
+
+ exampleItemModels.add(new ExampleItemModel(
+ R.id.nav_dds,
+ R.string.activity_dds_animated_dash_line_title,
+ R.string.activity_dds_animated_dash_line_description,
+ new Intent(MainActivity.this, AnimatedDashLineActivity.class),
+ null,
+ R.string.activity_dds_animated_dash_line_url, true, BuildConfig.MIN_SDK_VERSION));
+
exampleItemModels.add(new ExampleItemModel(
R.id.nav_basics,
R.string.activity_basic_simple_mapview_title,
diff --git a/MapboxAndroidDemo/src/global/java/com/mapbox/mapboxandroiddemo/account/LandingActivity.java b/MapboxAndroidDemo/src/global/java/com/mapbox/mapboxandroiddemo/account/LandingActivity.java
index 2060e6e92..f0cc4d6ee 100644
--- a/MapboxAndroidDemo/src/global/java/com/mapbox/mapboxandroiddemo/account/LandingActivity.java
+++ b/MapboxAndroidDemo/src/global/java/com/mapbox/mapboxandroiddemo/account/LandingActivity.java
@@ -7,6 +7,11 @@
import android.widget.CheckBox;
import android.widget.Toast;
+import com.afollestad.materialdialogs.DialogAction;
+import com.afollestad.materialdialogs.MaterialDialog;
+import com.google.firebase.perf.metrics.AddTrace;
+import com.mapbox.mapboxandroiddemo.MainActivity;
+import com.mapbox.mapboxandroiddemo.commons.AnalyticsTracker;
import com.github.javiersantos.materialstyleddialogs.MaterialStyledDialog;
import com.google.firebase.perf.metrics.AddTrace;
import com.mapbox.mapboxandroiddemo.MainActivity;
diff --git a/MapboxAndroidDemo/src/main/AndroidManifest.xml b/MapboxAndroidDemo/src/main/AndroidManifest.xml
index 6997bb0f4..6239ca1bd 100644
--- a/MapboxAndroidDemo/src/main/AndroidManifest.xml
+++ b/MapboxAndroidDemo/src/main/AndroidManifest.xml
@@ -718,6 +718,13 @@
android:name="android.support.PARENT_ACTIVITY"
android:value="com.mapbox.mapboxandroiddemo.MainActivity" />
+
+
+
diff --git a/MapboxAndroidDemo/src/main/java/com/mapbox/mapboxandroiddemo/examples/dds/AnimatedDashLineActivity.java b/MapboxAndroidDemo/src/main/java/com/mapbox/mapboxandroiddemo/examples/dds/AnimatedDashLineActivity.java
new file mode 100644
index 000000000..588ad1b3a
--- /dev/null
+++ b/MapboxAndroidDemo/src/main/java/com/mapbox/mapboxandroiddemo/examples/dds/AnimatedDashLineActivity.java
@@ -0,0 +1,338 @@
+package com.mapbox.mapboxandroiddemo.examples.dds;
+
+import android.animation.ValueAnimator;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.annotation.NonNull;
+import android.support.v7.app.AppCompatActivity;
+import android.util.Log;
+
+import com.mapbox.mapboxandroiddemo.R;
+import com.mapbox.mapboxsdk.Mapbox;
+import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
+import com.mapbox.mapboxsdk.maps.Style;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
+import com.mapbox.mapboxsdk.style.layers.Layer;
+import com.mapbox.mapboxsdk.style.layers.LineLayer;
+import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
+import com.mapbox.mapboxsdk.style.sources.VectorSource;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.exponential;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.interpolate;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.linear;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.match;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.rgb;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.rgba;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.stop;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.toColor;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.toRgba;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.zoom;
+import static com.mapbox.mapboxsdk.style.layers.Property.LINE_CAP_ROUND;
+import static com.mapbox.mapboxsdk.style.layers.Property.LINE_JOIN_ROUND;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineBlur;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineCap;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineColor;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineDasharray;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineJoin;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineOffset;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineWidth;
+
+/**
+ * Create an effect of animated and moving LineLayer dashes by rapidly adjusting the
+ * dash and gap lengths.
+ */
+public class AnimatedDashLineActivity extends AppCompatActivity implements OnMapReadyCallback {
+
+ private static final String ANIMATE_LINE_LAYER_ID = "animated_line_layer_id";
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+ private Handler handler;
+ private String TAG = "AnimatedDashLine";
+ private Layer animatedLineLayer;
+ private RefreshDashAndGapRunnable refreshDashAndGapRunnable;
+ private int animationSpeedMillseconds = 50;
+ private ValueAnimator animator;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Mapbox access token is configured here. This needs to be called either in your application
+ // object or in the same activity which contains the mapview.
+ Mapbox.getInstance(this, getString(R.string.access_token));
+
+ // This contains the MapView in XML and needs to be called after the access token is configured.
+ setContentView(R.layout.activity_animated_dash_line);
+
+ handler = new Handler();
+ mapView = findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(final MapboxMap mapboxMap) {
+ AnimatedDashLineActivity.this.mapboxMap = mapboxMap;
+
+// try {
+ mapboxMap.setStyle(Style.TRAFFIC_NIGHT
+ /*.withSource(new GeoJsonSource("animated_line_source", new URL(
+ "https://raw.githubusercontent.com/Chicago/osd-bike-routes/master/data/Bikeroutes.geojson"
+ ))
+ )*/, new Style.OnStyleLoaded() {
+ @Override
+ public void onStyleLoaded(@NonNull Style style) {
+// initAnimation();
+
+ style.addSource(new VectorSource("traffic-data-source-id", "mapbox://mapbox.mapbox-traffic-v1"));
+
+ LineLayer antsTrafficLayer = new LineLayer(ANIMATE_LINE_LAYER_ID,
+ "traffic-data-source-id").withProperties(
+ lineBlur(4f),
+
+ lineDasharray(new Float[] {2f, 2f}),
+
+ lineWidth(interpolate(exponential(1.5f), zoom(),
+ stop(6, 1),
+ stop(13, 4),
+ stop(18, match(get("class"), literal(0f),
+ stop("motorway", 18),
+ stop("trunk", 18),
+ stop("primary", 11),
+ stop("tertiary", 7),
+ stop("secondary", 7)
+ )),
+ stop(20, match(get("class"), literal(0f),
+ stop("motorway", 33),
+ stop("trunk", 33),
+ stop("primary", 18.5),
+ stop("tertiary", 14),
+ stop("secondary", 14)
+ )))),
+
+ lineColor(
+ match(get("congestion"), toColor(rgba(0, 0, 0,0)),
+ stop("low", toColor(rgb(62, 116, 85))),
+ stop("moderate", toColor(rgb(182, 116, 58))),
+ stop("heavy", toColor(rgb(205, 112, 112))),
+ stop("severe", toColor(rgb(102, 0, 17)))
+ )),
+
+ lineOffset(interpolate(exponential(1.5), zoom(),
+ stop(7, 0),
+ stop(9, 1),
+ stop(15, match(get("class"), literal(1f),
+ stop("motorway", 4),
+ stop("trunk", 4),
+ stop("primary", 4),
+ stop("tertiary", 3),
+ stop("secondary", 3)
+ )),
+ stop(18, match(get("class"), literal(0f),
+ stop("motorway", 11),
+ stop("trunk", 11),
+ stop("primary", 10),
+ stop("tertiary", 9),
+ stop("secondary", 9)
+ )),
+ stop(20, 21.5)
+ ))
+ );
+
+ antsTrafficLayer.setSourceLayer("traffic");
+ antsTrafficLayer.setFilter(match(get("class"), literal(false),
+ stop("motorway", literal(true)),
+ stop("trunk", literal(true)),
+ stop("primary", literal(true)),
+ stop("secondary", literal(true)),
+ stop("tertiary", literal(true))
+ ));
+ style.addLayerBelow(antsTrafficLayer, "bridge-oneway-arrows-blue-major");
+
+
+ animatedLineLayer = mapboxMap.getStyle().getLayer(ANIMATE_LINE_LAYER_ID);
+
+ Runnable runnable = new RefreshDashAndGapRunnable();
+ handler.postDelayed(runnable, animationSpeedMillseconds);
+ }
+ });
+
+ /*} catch (MalformedURLException malformedUrlException) {
+ Log.d("AnimatedDashLine", "Check the URL: " + malformedUrlException.getMessage());
+ }*/
+ }
+
+ private class RefreshDashAndGapRunnable implements Runnable {
+ private float valueOne, valueTwo, valueThree, valueFour, ValueFive;
+ private float dashLength = 3;
+ private float gapLength = 3;
+
+ // We divide the animation up into 40 totalNumberOfSteps to make careful use of the finite space in
+ // LineAtlas
+ private float totalNumberOfSteps = 40;
+
+ // A # of totalNumberOfSteps proportional to the dashLength are devoted to manipulating the dash
+ private float dashSteps = totalNumberOfSteps * dashLength / (gapLength + dashLength);
+
+ // A # of totalNumberOfSteps proportional to the gapLength are devoted to manipulating the gap
+ private float gapSteps = totalNumberOfSteps - dashSteps;
+
+ // The current currentStep #
+// private int currentStep = 0;
+ private int gap = 0;
+
+ private String TAG = "AnimatedDashLine";
+
+ @Override
+ public void run() {
+
+/*
+ if (gap >= totalNumberOfSteps) {
+ Log.d(TAG, "run: currentStep >= totalNumberOfSteps");
+ gap = 0;
+ }
+*/
+
+ Float[] newFloatArray = new Float[] {
+ 0f, Float.valueOf(gap++ / 10 % 4), 2f, 2f, 2f, 2f, 2f, 2f, 2f, 2f
+ };
+
+ mapboxMap.getStyle().getLayer(ANIMATE_LINE_LAYER_ID).setProperties(
+ lineDasharray(newFloatArray));
+ handler.postDelayed(this, animationSpeedMillseconds);
+ }
+ }
+
+ /*private class RefreshDashAndGapRunnable implements Runnable {
+ private float valueOne, valueTwo, valueThree, valueFour, ValueFive;
+ private float dashLength = 3;
+ private float gapLength = 3;
+
+ // We divide the animation up into 40 totalNumberOfSteps to make careful use of the finite space in
+ // LineAtlas
+ private float totalNumberOfSteps = 40;
+
+ // A # of totalNumberOfSteps proportional to the dashLength are devoted to manipulating the dash
+ private float dashSteps = totalNumberOfSteps * dashLength / (gapLength + dashLength);
+
+ // A # of totalNumberOfSteps proportional to the gapLength are devoted to manipulating the gap
+ private float gapSteps = totalNumberOfSteps - dashSteps;
+
+ // The current currentStep #
+ private int currentStep = 0;
+
+ private String TAG = "AnimatedDashLine";
+
+ @Override
+ public void run() {
+ Log.d(TAG, "RefreshDashAndGapRunnable run: ");
+ currentStep = currentStep + 1;
+ if (currentStep >= totalNumberOfSteps) {
+ Log.d(TAG, "run: currentStep >= totalNumberOfSteps");
+ currentStep = 0;
+ }
+ if (currentStep < dashSteps) {
+ Log.d(TAG, "run: currentStep < dashSteps");
+ valueOne = currentStep / dashSteps;
+ valueTwo = (1 - valueOne) * dashLength;
+ valueThree = gapLength;
+ valueFour = valueOne * dashLength;
+ ValueFive = 0;
+ } else {
+ valueOne = (currentStep - dashSteps) / (gapSteps);
+ valueTwo = 0;
+ valueThree = (1 - valueOne) * gapLength;
+ valueFour = dashLength;
+ ValueFive = valueOne * gapLength;
+ }
+ Log.d(TAG, "RefreshDashAndGapRunnable run: here");
+
+ Float[] newFloatArray = new Float[] {valueTwo, valueThree, valueFour, ValueFive};
+
+ mapboxMap.getStyle().getLayer("animated_line_layer_id").setProperties(
+ lineDasharray(newFloatArray));
+ Log.d(TAG, "RefreshDashAndGapRunnable run: layer done being gotten");
+ handler.postDelayed(this, animationSpeedMillseconds);
+ }
+ }*/
+
+ /* private void initAnimation() {
+ animator = ValueAnimator.ofFloat(0, 30);
+ animator.setDuration(animationSpeedMillseconds);
+ animator.setInterpolator(new LinearInterpolator());
+ animator.setRepeatMode(ValueAnimator.REVERSE);
+ animator.setRepeatCount(ValueAnimator.INFINITE);
+ animator.setStartDelay(1000);
+ animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ if (animatedLineLayer != null) {
+ animatedLineLayer.setProperties(lineDasharray(
+ new Float[] {0f, (Float) valueAnimator.getAnimatedValue(), 0f, (Float) valueAnimator.getAnimatedValue()}));
+ Log.d(TAG, "RefreshDashAndGapRunnable valueAnimator.getAnimatedValue() = "
+ + valueAnimator.getAnimatedValue());
+
+ }
+ }
+ });
+ animator.start();
+ }*/
+
+ // Add the mapView lifecycle to the activity's lifecycle methods
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ if (animator != null) {
+ animator.cancel();
+ }
+ mapView.onStop();
+ handler.removeCallbacks(refreshDashAndGapRunnable);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ refreshDashAndGapRunnable = null;
+ handler = null;
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+}
\ No newline at end of file
diff --git a/MapboxAndroidDemo/src/main/res/layout/activity_animated_dash_line.xml b/MapboxAndroidDemo/src/main/res/layout/activity_animated_dash_line.xml
new file mode 100644
index 000000000..1019c307d
--- /dev/null
+++ b/MapboxAndroidDemo/src/main/res/layout/activity_animated_dash_line.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MapboxAndroidDemo/src/main/res/values/descriptions_strings.xml b/MapboxAndroidDemo/src/main/res/values/descriptions_strings.xml
index d7bd97ab7..0523f374d 100644
--- a/MapboxAndroidDemo/src/main/res/values/descriptions_strings.xml
+++ b/MapboxAndroidDemo/src/main/res/values/descriptions_strings.xml
@@ -58,6 +58,8 @@
View satellite photos and click to outline an area of land.
Change SymbolLayer icons based on the camera\'s zoom level.
Set the radii of a circle layer\'s circles based on a data property.
+ Animated the gap size of a LineLayer for the appearance of moving lines.
+ Create a default marker with an InfoWindow.
Draw a polyline by parsing a GeoJSON file with the Mapbox Maps SDK.
Tap on various polygons to "select" them and toggle their colors.
Draw a vector polygon on a map with the Mapbox Maps SDK.
diff --git a/MapboxAndroidDemo/src/main/res/values/titles_strings.xml b/MapboxAndroidDemo/src/main/res/values/titles_strings.xml
index d0f4cca3f..98bfc1403 100644
--- a/MapboxAndroidDemo/src/main/res/values/titles_strings.xml
+++ b/MapboxAndroidDemo/src/main/res/values/titles_strings.xml
@@ -59,6 +59,8 @@
Satellite land select
Line gradient
Zoom-based icon switch
+ Animated line layer
+ Draw a marker
Draw a GeoJSON line
Draw a polygon
Draw a polygon with holes
diff --git a/MapboxAndroidDemo/src/main/res/values/urls_strings.xml b/MapboxAndroidDemo/src/main/res/values/urls_strings.xml
index eff39ccd8..e4601a0e5 100644
--- a/MapboxAndroidDemo/src/main/res/values/urls_strings.xml
+++ b/MapboxAndroidDemo/src/main/res/values/urls_strings.xml
@@ -56,6 +56,8 @@
https://i.imgur.com/tfbO1m4.png
https://i.imgur.com/sbWU4Ui.png
https://i.imgur.com/gVIfE3G.png
+ https://i.imgur.com/9JTOUQL.png
+ http://i.imgur.com/X59UoaY.png
https://i.imgur.com/Bs0X98z.png
http://i.imgur.com/v9X28id.png
https://i.imgur.com/6hcqbNw.png
@@ -63,6 +65,8 @@
http://i.imgur.com/19GZh8H.jpg
https://i.imgur.com/MrablT6.png
https://i.imgur.com/MSoIYmU.png
+ http://i.imgur.com/vbWTLIE.png
+ http://i.imgur.com/mCWbosy.png
http://i.imgur.com/PN3vyNJ.jpg
http://i.imgur.com/A0JL21Q.png
http://i.imgur.com/A227BEs.jpg