diff --git a/app/src/main/java/com/mapbox/services/android/navigation/testapp/activity/navigationui/EmbeddedNavigationActivity.java b/app/src/main/java/com/mapbox/services/android/navigation/testapp/activity/navigationui/EmbeddedNavigationActivity.java index 41eb4ec4461..8704980b938 100644 --- a/app/src/main/java/com/mapbox/services/android/navigation/testapp/activity/navigationui/EmbeddedNavigationActivity.java +++ b/app/src/main/java/com/mapbox/services/android/navigation/testapp/activity/navigationui/EmbeddedNavigationActivity.java @@ -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; @@ -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 call, Response 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(); @@ -187,6 +125,7 @@ public void onStop() { protected void onDestroy() { super.onDestroy(); navigationView.onDestroy(); + saveNightModeToPreferences(AppCompatDelegate.MODE_NIGHT_AUTO); } @Override @@ -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 call, Response 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); @@ -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); - } } diff --git a/app/src/main/res/drawable/ic_refresh.xml b/app/src/main/res/drawable/ic_refresh.xml new file mode 100644 index 00000000000..794ca6ad3cb --- /dev/null +++ b/app/src/main/res/drawable/ic_refresh.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_embedded_navigation.xml b/app/src/main/res/layout/activity_embedded_navigation.xml index df4e59de469..8155a43edef 100644 --- a/app/src/main/res/layout/activity_embedded_navigation.xml +++ b/app/src/main/res/layout/activity_embedded_navigation.xml @@ -1,5 +1,6 @@ - @@ -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"/> - + + + + + android:textSize="35sp" + android:visibility="gone" + app:layout_anchor="@id/spacer" + app:layout_anchorGravity="top"/> + + app:layout_anchorGravity="top"/> + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7cc924be299..8df5ae619fa 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -37,6 +37,7 @@ route_profile default_for_device default_for_device + current_night_mode Current route is not available Please select a longer route diff --git a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/MapboxNavigationActivity.java b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/MapboxNavigationActivity.java index 738b8047021..55efa7283f1 100644 --- a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/MapboxNavigationActivity.java +++ b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/MapboxNavigationActivity.java @@ -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; @@ -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); diff --git a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/NavigationView.java b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/NavigationView.java index 5ffa252e084..a4e009fdf7b 100644 --- a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/NavigationView.java +++ b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/NavigationView.java @@ -13,13 +13,13 @@ import android.support.design.widget.BottomSheetBehavior; import android.support.design.widget.CoordinatorLayout; import android.support.v4.app.FragmentActivity; -import android.support.v7.app.AppCompatDelegate; import android.util.AttributeSet; import android.view.View; import android.widget.ImageButton; import com.mapbox.api.directions.v5.models.DirectionsRoute; import com.mapbox.geojson.Point; +import com.mapbox.mapboxsdk.constants.MapboxConstants; import com.mapbox.mapboxsdk.maps.MapView; import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; @@ -84,7 +84,6 @@ public NavigationView(Context context, @Nullable AttributeSet attrs) { public NavigationView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO); ThemeSwitcher.setTheme(context, attrs); initializeView(); } @@ -95,7 +94,7 @@ public NavigationView(Context context, @Nullable AttributeSet attrs, int defStyl * @param savedInstanceState to restore state if not null */ public void onCreate(@Nullable Bundle savedInstanceState) { - mapView.setStyleUrl(ThemeSwitcher.retrieveMapStyle(getContext())); + updateSavedInstanceStateMapStyle(savedInstanceState); mapView.onCreate(savedInstanceState); updatePresenterState(savedInstanceState); navigationViewModel.onCreate(); @@ -407,6 +406,13 @@ private void initializeInstructionListListener() { navigationViewEventDispatcher)); } + private void updateSavedInstanceStateMapStyle(@Nullable Bundle savedInstanceState) { + if (savedInstanceState != null) { + String mapStyleUrl = ThemeSwitcher.retrieveMapStyle(getContext()); + savedInstanceState.putString(MapboxConstants.STATE_STYLE_URL, mapStyleUrl); + } + } + /** * Sets the {@link BottomSheetBehavior} based on the last state stored * in {@link Bundle} savedInstanceState. diff --git a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/ThemeSwitcher.java b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/ThemeSwitcher.java index 934f155d79f..3059978a5d3 100644 --- a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/ThemeSwitcher.java +++ b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/ThemeSwitcher.java @@ -105,6 +105,11 @@ static void setTheme(Context context, AttributeSet attrs) { context.setTheme(darkThemeEnabled ? darkTheme : lightTheme); } + static String retrieveMapStyle(Context context) { + TypedValue mapStyleAttr = resolveAttributeFromId(context, R.attr.navigationViewMapStyle); + return mapStyleAttr.string.toString(); + } + /** * Returns true if the current UI_MODE_NIGHT is enabled, false otherwise. * @@ -116,11 +121,6 @@ private static boolean isDarkThemeEnabled(Context context) { return uiMode == Configuration.UI_MODE_NIGHT_YES; } - static String retrieveMapStyle(Context context) { - TypedValue mapStyleAttr = resolveAttributeFromId(context, R.attr.navigationViewMapStyle); - return mapStyleAttr.string.toString(); - } - @NonNull private static TypedValue resolveAttributeFromId(Context context, int resId) { TypedValue outValue = new TypedValue(); diff --git a/libandroid-navigation-ui/src/main/res/layout/navigation_view_layout.xml b/libandroid-navigation-ui/src/main/res/layout/navigation_view_layout.xml index d1d45223052..08c08ce66ab 100644 --- a/libandroid-navigation-ui/src/main/res/layout/navigation_view_layout.xml +++ b/libandroid-navigation-ui/src/main/res/layout/navigation_view_layout.xml @@ -12,6 +12,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" app:mapbox_uiAttribution="false" + app:mapbox_styleUrl="?attr/navigationViewMapStyle" app:mapbox_uiCompass="false" app:mapbox_uiLogo="false"/>