-
Notifications
You must be signed in to change notification settings - Fork 319
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add route overview button and animation to NavigationView #967
Conversation
Attaching light and dark icons for route preview. @danesfeder |
Love the dynamic camera. @danesfeder is it easy enough to adjust the spacing between the sound and feedback icons in this PR as well so they better match iOS? the thinking being grouping things that obscure the map together makes them less intrusive overall -- thoughts @cjballard? also:
|
@brsbl sure thing and thanks! - would like @cjballard 👀 on this as well. I have them spaced a little more to create larger touch points. Hitting that feedback button accidentally when you're trying to mute is pretty jarring |
@brsbl @danesfeder Agreed. I think there's a middle ground we can hit that still reserves those touchpoints while grouping them more tightly and revealing more of the map. Maybe 10-20dp closer together could work. |
9528c6b
to
7ece39c
Compare
@cjballard Here's what the current setup looks like, let me know what you think / want to tweak 👍
|
@danesfeder Looks good to me! Only adjustment I might make is to make the separating line a bit shorter, closer to the height (but still a little taller) than the route preview icon: |
2ae7846
to
d60a781
Compare
@cjballard Updated: |
@danesfeder Looks good to me 👍 |
@cjballard awesome, thank you! @Guardiola31337 @devotaaabel will add tests to this PR tomorrow then will be good for 👀 |
386c01d
to
d0236e2
Compare
Tests added - this is good for 👀 |
Merge is causing issues with padding adjustments - this PR is no longer ready for review until these issues are fixed. |
c6c9676
to
35966d2
Compare
1ccb3e9
to
717f146
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall this look awesome 💯 Great job @danesfeder 👏
Really nice test coverage ❤️
Some minor comments.
@@ -509,6 +499,12 @@ public void onClick(View view) { | |||
navigationPresenter.onRecenterClick(); | |||
} | |||
}); | |||
routeOverviewBtn.setOnClickListener(new OnClickListener() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about extracting the listeners into class properties?
@@ -187,6 +200,14 @@ private RouteInformation buildRouteInformationFromLocation(Location location, Ro | |||
return RouteInformation.create(null, location, routeProgress); | |||
} | |||
|
|||
@NonNull | |||
private RouteInformation buildRouteInformationFromRouteProgress(RouteProgress routeProgress) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor thing - IMO buildRouteInformationFrom(RouteProgress routeProgress)
would be clearer and to the point. What do you think?
private void animateCameraForRouteOverview(RouteInformation routeInformation, int[] padding) { | ||
Camera cameraEngine = navigation.getCameraEngine(); | ||
|
||
CameraPosition resetPosition = new CameraPosition.Builder().tilt(0).bearing(0).build(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can move these two lines after the guard clause avoiding instantiating them if invalidPoints
is true
.
if (invalidPoints) { | ||
return; | ||
} | ||
final LatLngBounds routeBounds = convertRoutePointsToLatLngBounds(routePoints); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about extracting this preparation block of code into a well-named private
method? (Including the two lines mentioned above ☝️)
ImageButton routeOverviewBtn = findViewById(R.id.routeOverviewBtn); | ||
boolean isDarkThemeEnabled = ThemeSwitcher.isDarkThemeEnabled(getContext()); | ||
Drawable routeOverviewDrawable; | ||
if (isDarkThemeEnabled) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a custom attribute to the nav theme so it's just added upon inflation and remove the if else
check?
LineString lineString = LineString.fromPolyline(route.geometry(), Constants.PRECISION_6); | ||
return lineString.coordinates(); | ||
} | ||
return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should consider returning a Null Object instead or even better try to getting rid of it at all (maybe returning an empty list?). If not, code becomes defensive and full of null
checks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually if the route
in setupLineStringAndBearing
is null
L#85 will cause a NPE right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In any case, guard clauses normally are at the beginning of the method representing the unexpected behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also saw the same exact code in DynamicCameraTest.java
(generateRouteCoordinates
). Should be abstracted and accessible to the implementation classes?
@@ -145,6 +149,44 @@ public void onInformationFromLocationAndProgress_engineCreatesCorrectBearing() t | |||
assertEquals(100f, bearing, DELTA); | |||
} | |||
|
|||
@Test | |||
public void onInformationFromRoute_engineCreatesOverviewPointList() throws Exception { | |||
MapboxMap mapboxMap = mock(MapboxMap.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor thing - Could we extract some shared "arrangement" code into private
methods and used it across the tests? This applies to MapWaynameTest
as well.
5cb0ecc
to
74d0d02
Compare
@Guardiola31337 Updated - I skipped your comment on |
74d0d02
to
a5af67c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@danesfeder Some minor new comments from the latest changes.
import com.mapbox.mapboxsdk.maps.MapboxMap; | ||
import com.mapbox.services.android.navigation.ui.v5.utils.ViewUtils; | ||
|
||
public class NavigationSnapshotReadyCallback implements MapboxMap.SnapshotReadyCallback { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Access can be package-private
private NavigationView navigationView; | ||
private NavigationViewModel navigationViewModel; | ||
|
||
public NavigationSnapshotReadyCallback(NavigationView navigationView, NavigationViewModel navigationViewModel) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Access can be package-private
int uiMode = context.getResources().getConfiguration().uiMode | ||
& Configuration.UI_MODE_NIGHT_MASK; | ||
boolean darkThemeEnabled = uiMode == Configuration.UI_MODE_NIGHT_YES; | ||
boolean darkThemeEnabled = isDarkThemeEnabled(context); | ||
updatePreferencesDarkEnabled(context, darkThemeEnabled); | ||
|
||
// Check for custom theme from NavigationLauncher |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this comment necessary?
@@ -187,6 +200,14 @@ private RouteInformation buildRouteInformationFromLocation(Location location, Ro | |||
return RouteInformation.create(null, location, routeProgress); | |||
} | |||
|
|||
@NonNull | |||
private RouteInformation buildRouteInformationFrom(RouteProgress routeProgress) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't see that we had other buildRouteInformationFrom
methods. Maybe we should leave as it was. Sorry for the confusion.
if (invalidPoints) { | ||
return; | ||
} | ||
CameraUpdate resetUpdate = buildResetCameraUpdate(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CameraUpdate resetUpdate = buildResetCameraUpdate(); | ||
final CameraUpdate overviewUpdate = buildOverviewCameraUpdate(padding, routePoints); | ||
|
||
mapboxMap.animateCamera(resetUpdate, 150, new MapboxMap.CancelableCallback() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about extracting the listeners into class properties?
@@ -173,4 +214,12 @@ private DirectionsRoute buildDirectionsRoute() throws IOException { | |||
DirectionsResponse response = gson.fromJson(body, DirectionsResponse.class); | |||
return response.routes().get(0); | |||
} | |||
|
|||
private List<Point> generateRouteCoordinates(DirectionsRoute route) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -48,8 +49,12 @@ public static Bitmap loadBitmapFromView(View view) { | |||
return null; | |||
} | |||
|
|||
public static float dpToPx(Context context, int dp) { | |||
public static int[] buildRouteOverviewPadding(Context context) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't sound like a View
utility. It's only used in NavigationView
. IMO, objects and methods should live/be where their context is. From my experience utility classes become a drawer easily and we should treat them carefully.
@@ -59,20 +63,36 @@ public double zoom(RouteInformation routeInformation) { | |||
return CAMERA_ZOOM; | |||
} | |||
|
|||
@Override | |||
public List<Point> overview(RouteInformation routeInformation) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO overview
is getting too long.
What about extracting blocks of code into well-named private methods and simplifying conditional expressions somehow?
We should keep public
methods as clean as possible so they read like pseudocode (i.e. no conditionals, for
s, etc.).
63409b0
to
47c98ea
Compare
47c98ea
to
512390e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well done @danesfeder
Closes #950
TODO:
Point
Animation running wired up to the
X
button:cc @brsbl