diff --git a/MapboxAndroidDemo/src/global/java/com/mapbox/mapboxandroiddemo/MainActivity.java b/MapboxAndroidDemo/src/global/java/com/mapbox/mapboxandroiddemo/MainActivity.java index 04122e47f..7cc797bec 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; @@ -630,6 +631,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, @@ -1607,6 +1617,22 @@ private void initializeModels() { null, R.string.activity_dds_circle_icon_toggle_on_click_url, true, 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 f80ecff95..6d60a8474 100644 --- a/MapboxAndroidDemo/src/main/AndroidManifest.xml +++ b/MapboxAndroidDemo/src/main/AndroidManifest.xml @@ -782,6 +782,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 43a2759f4..70c383747 100644 --- a/MapboxAndroidDemo/src/main/res/values/descriptions_strings.xml +++ b/MapboxAndroidDemo/src/main/res/values/descriptions_strings.xml @@ -59,6 +59,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 2a69a83ce..4feb996bc 100644 --- a/MapboxAndroidDemo/src/main/res/values/titles_strings.xml +++ b/MapboxAndroidDemo/src/main/res/values/titles_strings.xml @@ -61,6 +61,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 418a062f8..f95b5dfa8 100644 --- a/MapboxAndroidDemo/src/main/res/values/urls_strings.xml +++ b/MapboxAndroidDemo/src/main/res/values/urls_strings.xml @@ -57,6 +57,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 @@ -67,6 +69,8 @@ https://i.imgur.com/GE1DZMp.png https://i.imgur.com/5ewVbqM.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