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
Guardiola31337
left a comment
There was a problem hiding this comment.
Overall this look awesome 💯 Great job @danesfeder 👏
Really nice test coverage ❤️
Some minor comments.
| navigationPresenter.onRecenterClick(); | ||
| } | ||
| }); | ||
| routeOverviewBtn.setOnClickListener(new OnClickListener() { |
There was a problem hiding this comment.
What about extracting the listeners into class properties?
| } | ||
|
|
||
| @NonNull | ||
| private RouteInformation buildRouteInformationFromRouteProgress(RouteProgress routeProgress) { |
There was a problem hiding this comment.
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.
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.
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.
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.
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.
Actually if the route in setupLineStringAndBearing is null L#85 will cause a NPE right?
There was a problem hiding this comment.
In any case, guard clauses normally are at the beginning of the method representing the unexpected behavior.
There was a problem hiding this comment.
Also saw the same exact code in DynamicCameraTest.java (generateRouteCoordinates). Should be abstracted and accessible to the implementation classes?
|
|
||
| @Test | ||
| public void onInformationFromRoute_engineCreatesOverviewPointList() throws Exception { | ||
| MapboxMap mapboxMap = mock(MapboxMap.class); |
There was a problem hiding this comment.
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
Guardiola31337
left a comment
There was a problem hiding this comment.
@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.
Access can be package-private
| private NavigationView navigationView; | ||
| private NavigationViewModel navigationViewModel; | ||
|
|
||
| public NavigationSnapshotReadyCallback(NavigationView navigationView, NavigationViewModel navigationViewModel) { |
There was a problem hiding this comment.
Access can be package-private
| boolean darkThemeEnabled = isDarkThemeEnabled(context); | ||
| updatePreferencesDarkEnabled(context, darkThemeEnabled); | ||
|
|
||
| // Check for custom theme from NavigationLauncher |
There was a problem hiding this comment.
Is this comment necessary?
| } | ||
|
|
||
| @NonNull | ||
| private RouteInformation buildRouteInformationFrom(RouteProgress routeProgress) { |
There was a problem hiding this comment.
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(); |
| CameraUpdate resetUpdate = buildResetCameraUpdate(); | ||
| final CameraUpdate overviewUpdate = buildOverviewCameraUpdate(padding, routePoints); | ||
|
|
||
| mapboxMap.animateCamera(resetUpdate, 150, new MapboxMap.CancelableCallback() { |
There was a problem hiding this comment.
What about extracting the listeners into class properties?
| return response.routes().get(0); | ||
| } | ||
|
|
||
| private List<Point> generateRouteCoordinates(DirectionsRoute route) { |
| } | ||
|
|
||
| public static float dpToPx(Context context, int dp) { | ||
| public static int[] buildRouteOverviewPadding(Context context) { |
There was a problem hiding this comment.
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.
| } | ||
|
|
||
| @Override | ||
| public List<Point> overview(RouteInformation routeInformation) { |
There was a problem hiding this comment.
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, fors, etc.).
63409b0 to
47c98ea
Compare
47c98ea to
512390e
Compare
Guardiola31337
left a comment
There was a problem hiding this comment.
Well done @danesfeder ![]()





Closes #950
TODO:
PointAnimation running wired up to the

Xbutton:cc @brsbl