Directions route with gradient
NOTE
This example is a part of the Mapbox Android Demo app. You can find the values for all referenced resources in the res
directory. For example, see res/values/activity_strings.xml
for R.string.*
references used in this example.
Directions API pricing
Products used within the Mapbox Java SDK, including the Directions API, are individually billed. For pricing information, see the documentation for the Directions API.
<?xml version="1.0" encoding="utf-8"?><FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:mapbox="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".examples.dds.LineGradientActivity"> <com.mapbox.mapboxsdk.maps.MapViewandroid:id="@+id/mapView"android:layout_width="match_parent"android:layout_height="match_parent"mapbox:mapbox_cameraTargetLat="-6.161038"mapbox:mapbox_cameraTargetLng="106.825398"mapbox:mapbox_cameraZoom="9.8" /> </FrameLayout>
package com.mapbox.mapboxandroiddemo.examples.javaservices; import android.os.Bundle;import android.widget.Toast; import com.mapbox.api.directions.v5.DirectionsCriteria;import com.mapbox.api.directions.v5.MapboxDirections;import com.mapbox.api.directions.v5.models.DirectionsResponse;import com.mapbox.api.directions.v5.models.DirectionsRoute;import com.mapbox.geojson.Feature;import com.mapbox.geojson.FeatureCollection;import com.mapbox.geojson.LineString;import com.mapbox.geojson.Point;import com.mapbox.mapboxandroiddemo.R;import com.mapbox.mapboxsdk.Mapbox;import com.mapbox.mapboxsdk.geometry.LatLng;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.layers.LineLayer;import com.mapbox.mapboxsdk.style.layers.Property;import com.mapbox.mapboxsdk.style.layers.SymbolLayer;import com.mapbox.mapboxsdk.style.sources.GeoJsonOptions;import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;import com.mapbox.mapboxsdk.utils.BitmapUtils; import androidx.annotation.NonNull;import androidx.appcompat.app.AppCompatActivity;import retrofit2.Call;import retrofit2.Callback;import retrofit2.Response;import timber.log.Timber; import static android.graphics.Color.parseColor;import static com.mapbox.core.constants.Constants.PRECISION_6;import static com.mapbox.mapboxsdk.style.expressions.Expression.color;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.lineProgress;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.stop;import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconIgnorePlacement;import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconOffset;import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineCap;import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineGradient;import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineJoin;import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineWidth; /*** Make a directions request with the Mapbox Directions API and then draw a line behind a moving* SymbolLayer icon which moves along the Directions response route.*/public class DirectionsGradientLineActivity extends AppCompatActivity implements MapboxMap.OnMapClickListener { private static final String ORIGIN_ICON_ID = "origin-icon-id";private static final String DESTINATION_ICON_ID = "destination-icon-id";private static final String ROUTE_LAYER_ID = "route-layer-id";private static final String ROUTE_LINE_SOURCE_ID = "route-source-id";private static final String ICON_LAYER_ID = "icon-layer-id";private static final String ICON_SOURCE_ID = "icon-source-id";private MapView mapView;private MapboxMap mapboxMap;private DirectionsRoute currentRoute;private MapboxDirections client; // Adjust variables below to change the example's UIprivate static Point ORIGIN_POINT = Point.fromLngLat(106.7140180, -6.149120972);private static Point DESTINATION_POINT = Point.fromLngLat(106.9687635, -6.304752436);private static final float LINE_WIDTH = 6f;private static final String ORIGIN_COLOR = "#2096F3";private static final String DESTINATION_COLOR = "#F84D4D"; @Overrideprotected 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_javaservices_directions_gradient); // Setup the MapViewmapView = findViewById(R.id.mapView);mapView.onCreate(savedInstanceState);mapView.getMapAsync(new OnMapReadyCallback() {@Overridepublic void onMapReady(@NonNull MapboxMap mapboxMap) {DirectionsGradientLineActivity.this.mapboxMap = mapboxMap;mapboxMap.setStyle(new Style.Builder().fromUri(Style.DARK).withImage(ORIGIN_ICON_ID, BitmapUtils.getBitmapFromDrawable(getResources().getDrawable(R.drawable.blue_marker))).withImage(DESTINATION_ICON_ID, BitmapUtils.getBitmapFromDrawable(getResources().getDrawable(R.drawable.red_marker))), new Style.OnStyleLoaded() {@Overridepublic void onStyleLoaded(@NonNull Style style) {initSources(style);initLayers(style); // Get the directions route from the Mapbox Directions APIgetRoute(mapboxMap, ORIGIN_POINT, DESTINATION_POINT); mapboxMap.addOnMapClickListener(DirectionsGradientLineActivity.this); Toast.makeText(DirectionsGradientLineActivity.this,getString(R.string.tap_map_instruction_gradient_directions), Toast.LENGTH_SHORT).show();}});}});} /*** Add the route and marker sources to the map*/private void initSources(@NonNull Style loadedMapStyle) {loadedMapStyle.addSource(new GeoJsonSource(ROUTE_LINE_SOURCE_ID, new GeoJsonOptions().withLineMetrics(true)));loadedMapStyle.addSource(new GeoJsonSource(ICON_SOURCE_ID, getOriginAndDestinationFeatureCollection()));} /*** Util method that returns a {@link FeatureCollection} with the latest origin and destination locations.** @return a {@link FeatureCollection} to be used for creating a new {@link GeoJsonSource} or* updating a source's GeoJSON.*/private FeatureCollection getOriginAndDestinationFeatureCollection() {Feature originFeature = Feature.fromGeometry(ORIGIN_POINT);originFeature.addStringProperty("originDestination", "origin");Feature destinationFeature = Feature.fromGeometry(DESTINATION_POINT);destinationFeature.addStringProperty("originDestination", "destination");return FeatureCollection.fromFeatures(new Feature[] {originFeature, destinationFeature});} /*** Add the route and marker icon layers to the map*/private void initLayers(@NonNull Style loadedMapStyle) {// Add the LineLayer to the map. This layer will display the directions route.loadedMapStyle.addLayer(new LineLayer(ROUTE_LAYER_ID, ROUTE_LINE_SOURCE_ID).withProperties(lineCap(Property.LINE_CAP_ROUND),lineJoin(Property.LINE_JOIN_ROUND),lineWidth(LINE_WIDTH),lineGradient(interpolate(linear(), lineProgress(), // This is where the gradient color effect is set. 0 -> 1 makes it a two-color gradient// See LineGradientActivity for an example of a 2+ multiple color gradient line.stop(0f, color(parseColor(ORIGIN_COLOR))),stop(1f, color(parseColor(DESTINATION_COLOR))))))); // Add the SymbolLayer to the map to show the origin and destination pin markersloadedMapStyle.addLayer(new SymbolLayer(ICON_LAYER_ID, ICON_SOURCE_ID).withProperties(iconImage(match(get("originDestination"), literal("origin"),stop("origin", ORIGIN_ICON_ID),stop("destination", DESTINATION_ICON_ID))),iconIgnorePlacement(true),iconAllowOverlap(true),iconOffset(new Float[] {0f, -4f})));} /*** Make a request to the Mapbox Directions API. Once successful, pass the route to the* route layer.** @param mapboxMap the Mapbox map object that the route will be drawn on* @param origin the starting point of the route* @param destination the desired finish point of the route*/private void getRoute(MapboxMap mapboxMap, Point origin, Point destination) {client = MapboxDirections.builder().origin(origin).destination(destination).overview(DirectionsCriteria.OVERVIEW_FULL).profile(DirectionsCriteria.PROFILE_WALKING).accessToken(getString(R.string.access_token)).build();client.enqueueCall(new Callback<DirectionsResponse>() {@Overridepublic void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {// You can get the generic HTTP info about the responseTimber.d("Response code: %s", response.code()); if (response.body() == null) {Timber.e("No routes found, make sure you set the right user and access token.");return;} else if (response.body().routes().size() < 1) {Timber.e("No routes found");return;} // Get the Direction API response's routecurrentRoute = response.body().routes().get(0); if (currentRoute != null) {if (mapboxMap != null) {mapboxMap.getStyle(new Style.OnStyleLoaded() {@Overridepublic void onStyleLoaded(@NonNull Style style) { // Retrieve and update the source designated for showing the directions routeGeoJsonSource originDestinationPointGeoJsonSource = style.getSourceAs(ICON_SOURCE_ID); if (originDestinationPointGeoJsonSource != null) {originDestinationPointGeoJsonSource.setGeoJson(getOriginAndDestinationFeatureCollection());} // Retrieve and update the source designated for showing the directions routeGeoJsonSource lineLayerRouteGeoJsonSource = style.getSourceAs(ROUTE_LINE_SOURCE_ID); // Create a LineString with the directions route's geometry and// reset the GeoJSON source for the route LineLayer sourceif (lineLayerRouteGeoJsonSource != null) {// Create the LineString from the list of coordinates and then make a GeoJSON// FeatureCollection so we can add the line to our map as a layer.LineString lineString = LineString.fromPolyline(currentRoute.geometry(), PRECISION_6);lineLayerRouteGeoJsonSource.setGeoJson(Feature.fromGeometry(lineString));}}});}} else {Timber.d("Directions route is null");Toast.makeText(DirectionsGradientLineActivity.this,getString(R.string.route_can_not_be_displayed), Toast.LENGTH_SHORT).show();}} @Overridepublic void onFailure(Call<DirectionsResponse> call, Throwable throwable) {Toast.makeText(DirectionsGradientLineActivity.this,getString(R.string.route_call_failure), Toast.LENGTH_SHORT).show();}});} @Overridepublic boolean onMapClick(@NonNull LatLng mapClickPoint) {// Move the destination point to wherever the map was tappedDESTINATION_POINT = Point.fromLngLat(mapClickPoint.getLongitude(), mapClickPoint.getLatitude()); // Get a new Directions API route to that new destination and eventually re-draw the// gradient route line.getRoute(mapboxMap, ORIGIN_POINT, DESTINATION_POINT);return true;} @Overridepublic void onResume() {super.onResume();mapView.onResume();} @Overrideprotected void onStart() {super.onStart();mapView.onStart();} @Overrideprotected void onStop() {super.onStop();mapView.onStop();} @Overridepublic void onPause() {super.onPause();mapView.onPause();} @Overrideprotected void onSaveInstanceState(Bundle outState) {super.onSaveInstanceState(outState);mapView.onSaveInstanceState(outState);} @Overrideprotected void onDestroy() {super.onDestroy();// Cancel the Directions API requestif (client != null) {client.cancelCall();}if (mapboxMap != null) {mapboxMap.removeOnMapClickListener(this);}mapView.onDestroy();} @Overridepublic void onLowMemory() {super.onLowMemory();mapView.onLowMemory();}}
Was this example helpful?