Skip to content

Commit

Permalink
Use theme attribute to update MapView map style URL (#1018)
Browse files Browse the repository at this point in the history
* Use theme attribute to update MapView map style URL

* Add night mode toggle example to embedded navigation Activity
  • Loading branch information
danesfeder authored Jun 21, 2018
1 parent 8d9b6b4 commit bf5b2f1
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 103 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
package com.mapbox.services.android.navigation.testapp.activity.navigationui;

import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.location.Location;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.BottomSheetBehavior;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.AppCompatDelegate;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.AbsoluteSizeSpan;
Expand All @@ -34,105 +39,38 @@
public class EmbeddedNavigationActivity extends AppCompatActivity implements OnNavigationReadyCallback,
NavigationListener, ProgressChangeListener, InstructionListListener {

private static final Point ORIGIN = Point.fromLngLat(-77.03194990754128, 38.909664963450105);
private static final Point DESTINATION = Point.fromLngLat(-77.0270025730133, 38.91057077063121);

private NavigationView navigationView;
private View spacer;
private TextView speedWidget;
private static final Point ORIGIN = Point.fromLngLat(-77.03194990754128, 38.909664963450105);
private static final Point DESTINATION = Point.fromLngLat(-77.0270025730133, 38.91057077063121);
private FloatingActionButton fabNightModeToggle;

private boolean bottomSheetVisible = true;
private boolean instructionListShown = false;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
setTheme(R.style.Theme_AppCompat_Light_NoActionBar);
initNightMode();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_embedded_navigation);
navigationView = findViewById(R.id.navigationView);
navigationView.onCreate(savedInstanceState);

fabNightModeToggle = findViewById(R.id.fabToggleNightMode);
speedWidget = findViewById(R.id.speed_limit);
spacer = findViewById(R.id.spacer);
setSpeedWidgetAnchor(R.id.summaryBottomSheet);

navigationView.onCreate(savedInstanceState);
navigationView.initialize(this);
}

/**
* Sets the anchor of the spacer for the speed widget, thus setting the anchor for the speed widget
* (The speed widget is anchored to the spacer, which is there because padding between items and
* their anchors in CoordinatorLayouts is finicky.
* @param res resource for view of which to anchor the spacer
*/
private void setSpeedWidgetAnchor(@IdRes int res) {
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) spacer.getLayoutParams();
layoutParams.setAnchorId(res);
spacer.setLayoutParams(layoutParams);
}

@Override
public void onNavigationReady() {
fetchRoute();
}

private void startNavigation(DirectionsRoute directionsRoute) {
NavigationViewOptions.Builder options =
NavigationViewOptions.builder()
.navigationListener(this)
.directionsRoute(directionsRoute)
.shouldSimulateRoute(true)
.progressChangeListener(this)
.instructionListListener(this);
setBottomSheetCallback(options);

navigationView.startNavigation(options.build());
}

private void fetchRoute() {
NavigationRoute.builder(this)
.accessToken(Mapbox.getAccessToken())
.origin(ORIGIN)
.destination(DESTINATION)
.alternatives(true)
.build()
.getRoute(new SimplifiedCallback() {
@Override
public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
DirectionsRoute directionsRoute = response.body().routes().get(0);
startNavigation(directionsRoute);
}
});
}

private void setBottomSheetCallback(NavigationViewOptions.Builder options) {
options.bottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
switch (newState) {
case BottomSheetBehavior.STATE_HIDDEN:
bottomSheetVisible = false;
setSpeedWidgetAnchor(R.id.recenterBtn);
break;
case BottomSheetBehavior.STATE_EXPANDED:
bottomSheetVisible = true;
break;
case BottomSheetBehavior.STATE_SETTLING:
if (!bottomSheetVisible) {
// View needs to be anchored to the bottom sheet before it is finished expanding
// because of the animation
setSpeedWidgetAnchor(R.id.summaryBottomSheet);
}
break;
default:
return;
}
}

@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
}

@Override
public void onStart() {
super.onStart();
Expand Down Expand Up @@ -187,6 +125,7 @@ public void onStop() {
protected void onDestroy() {
super.onDestroy();
navigationView.onDestroy();
saveNightModeToPreferences(AppCompatDelegate.MODE_NIGHT_AUTO);
}

@Override
Expand All @@ -210,6 +149,134 @@ public void onProgressChange(Location location, RouteProgress routeProgress) {
setSpeed(location);
}

@Override
public void onInstructionListVisibilityChanged(boolean shown) {
instructionListShown = shown;
speedWidget.setVisibility(shown ? View.GONE : View.VISIBLE);
if (instructionListShown) {
fabNightModeToggle.hide();
} else if (bottomSheetVisible) {
fabNightModeToggle.show();
}
}

private void startNavigation(DirectionsRoute directionsRoute) {
NavigationViewOptions.Builder options =
NavigationViewOptions.builder()
.navigationListener(this)
.directionsRoute(directionsRoute)
.shouldSimulateRoute(true)
.progressChangeListener(this)
.instructionListListener(this);
setBottomSheetCallback(options);
setupNightModeFab();

navigationView.startNavigation(options.build());
}

private void fetchRoute() {
NavigationRoute.builder(this)
.accessToken(Mapbox.getAccessToken())
.origin(ORIGIN)
.destination(DESTINATION)
.alternatives(true)
.build()
.getRoute(new SimplifiedCallback() {
@Override
public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
DirectionsRoute directionsRoute = response.body().routes().get(0);
startNavigation(directionsRoute);
}
});
}

/**
* Sets the anchor of the spacer for the speed widget, thus setting the anchor for the speed widget
* (The speed widget is anchored to the spacer, which is there because padding between items and
* their anchors in CoordinatorLayouts is finicky.
*
* @param res resource for view of which to anchor the spacer
*/
private void setSpeedWidgetAnchor(@IdRes int res) {
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) spacer.getLayoutParams();
layoutParams.setAnchorId(res);
spacer.setLayoutParams(layoutParams);
}

private void setBottomSheetCallback(NavigationViewOptions.Builder options) {
options.bottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
switch (newState) {
case BottomSheetBehavior.STATE_HIDDEN:
bottomSheetVisible = false;
fabNightModeToggle.hide();
setSpeedWidgetAnchor(R.id.recenterBtn);
break;
case BottomSheetBehavior.STATE_EXPANDED:
bottomSheetVisible = true;
break;
case BottomSheetBehavior.STATE_SETTLING:
if (!bottomSheetVisible) {
// View needs to be anchored to the bottom sheet before it is finished expanding
// because of the animation
fabNightModeToggle.show();
setSpeedWidgetAnchor(R.id.summaryBottomSheet);
}
break;
default:
return;
}
}

@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
}

private void setupNightModeFab() {
fabNightModeToggle.setOnClickListener(view -> toggleNightMode());
}

private void toggleNightMode() {
int currentNightMode = getCurrentNightMode();
alternateNightMode(currentNightMode);
}

private void initNightMode() {
int nightMode = retrieveNightModeFromPreferences();
AppCompatDelegate.setDefaultNightMode(nightMode);
}

private int getCurrentNightMode() {
return getResources().getConfiguration().uiMode
& Configuration.UI_MODE_NIGHT_MASK;
}

private void alternateNightMode(int currentNightMode) {
int newNightMode;
if (currentNightMode == Configuration.UI_MODE_NIGHT_YES) {
newNightMode = AppCompatDelegate.MODE_NIGHT_NO;
} else {
newNightMode = AppCompatDelegate.MODE_NIGHT_YES;
}
saveNightModeToPreferences(newNightMode);
recreate();
}

private int retrieveNightModeFromPreferences() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
return preferences.getInt(getString(R.string.current_night_mode), AppCompatDelegate.MODE_NIGHT_AUTO);
}

private void saveNightModeToPreferences(int nightMode) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = preferences.edit();
editor.putInt(getString(R.string.current_night_mode), nightMode);
editor.apply();
}

private void setSpeed(Location location) {
String string = String.format("%d\nMPH", (int) (location.getSpeed() * 2.2369));
int mphTextSize = getResources().getDimensionPixelSize(R.dimen.mph_text_size);
Expand All @@ -227,10 +294,4 @@ private void setSpeed(Location location) {
speedWidget.setVisibility(View.VISIBLE);
}
}

@Override
public void onInstructionListVisibilityChanged(boolean shown) {
instructionListShown = shown;
speedWidget.setVisibility(shown ? View.GONE : View.VISIBLE);
}
}
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/ic_refresh.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,6v3l4,-4 -4,-4v3c-4.42,0 -8,3.58 -8,8 0,1.57 0.46,3.03 1.24,4.26L6.7,14.8c-0.45,-0.83 -0.7,-1.79 -0.7,-2.8 0,-3.31 2.69,-6 6,-6zM18.76,7.74L17.3,9.2c0.44,0.84 0.7,1.79 0.7,2.8 0,3.31 -2.69,6 -6,6v-3l-4,4 4,4v-3c4.42,0 8,-3.58 8,-8 0,-1.57 -0.46,-3.03 -1.24,-4.26z"/>
</vector>
44 changes: 30 additions & 14 deletions app/src/main/res/layout/activity_embedded_navigation.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
Expand All @@ -8,28 +9,43 @@
android:id="@+id/navigationView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:navigationLightTheme="@style/CustomNavigationView"
app:navigationDarkTheme="@style/NavigationViewDark"/>
<TextView
app:navigationDarkTheme="@style/NavigationViewDark"
app:navigationLightTheme="@style/CustomNavigationView"/>

<android.support.design.widget.FloatingActionButton
android:id="@+id/fabToggleNightMode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|start"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:tint="@android:color/white"
app:layout_anchor="@id/spacer"
app:layout_anchorGravity="top|end"
app:srcCompat="@drawable/ic_refresh"/>

<TextView
android:id="@+id/speed_limit"
android:textSize="35sp"
android:padding="6dp"
app:layout_anchorGravity="top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:gravity="center"
android:layout_marginLeft="16dp"
android:background="@android:color/white"
android:elevation="3dp"
app:layout_anchor="@id/spacer"
android:gravity="center"
android:padding="6dp"
android:textColor="@android:color/black"
android:background="@android:color/white"
android:visibility="gone"/>
android:textSize="35sp"
android:visibility="gone"
app:layout_anchor="@id/spacer"
app:layout_anchorGravity="top"/>

<View
android:id="@+id/spacer"
android:layout_width="wrap_content"
android:layout_height="6dp"
android:id="@+id/spacer"
android:layout_gravity="top"
android:background="@android:color/transparent"
app:layout_anchorGravity="top"
android:layout_gravity="top"/>
app:layout_anchorGravity="top"/>

</android.support.design.widget.CoordinatorLayout>
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
<string name="route_profile_key" translatable="false">route_profile</string>
<string name="default_locale" translatable="false">default_for_device</string>
<string name="default_unit_type" translatable="false">default_for_device</string>
<string name="current_night_mode" translatable="false">current_night_mode</string>

<string name="error_route_not_available">Current route is not available</string>
<string name="error_select_longer_route">Please select a longer route</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.AppCompatDelegate;

import com.mapbox.api.directions.v5.DirectionsCriteria;
import com.mapbox.api.directions.v5.models.DirectionsRoute;
Expand All @@ -26,6 +27,7 @@ public class MapboxNavigationActivity extends AppCompatActivity implements OnNav
protected void onCreate(@Nullable Bundle savedInstanceState) {
setTheme(R.style.Theme_AppCompat_NoActionBar);
super.onCreate(savedInstanceState);
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO);
setContentView(R.layout.activity_navigation);
navigationView = findViewById(R.id.navigationView);
navigationView.onCreate(savedInstanceState);
Expand Down
Loading

0 comments on commit bf5b2f1

Please sign in to comment.