Skip to content

Commit 6eb307a

Browse files
committed
Add ability to display / select alternative routes (#1333)
* Add example test Activity for Navigation Test Application * Add ability to display / select alternative routes
1 parent 1791937 commit 6eb307a

File tree

14 files changed

+187
-218
lines changed

14 files changed

+187
-218
lines changed

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ android {
1818
versionCode 1
1919
versionName "0.1"
2020
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
21+
vectorDrawables.useSupportLibrary = true
2122
}
2223

2324
buildTypes {

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
<activity
1919
android:name=".example.ui.ExampleActivity"
2020
android:screenOrientation="portrait"
21-
android:windowSoftInputMode="stateHidden|adjustResize">
21+
android:windowSoftInputMode="stateHidden|adjustNothing">
2222
<intent-filter>
2323
<action android:name="android.intent.action.MAIN"/>
2424
<category android:name="android.intent.category.LAUNCHER"/>

app/src/main/java/com/mapbox/services/android/navigation/testapp/example/ui/ExampleActivity.kt

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import android.os.Bundle
77
import android.support.design.widget.BottomSheetBehavior
88
import android.support.transition.TransitionManager
99
import android.support.v7.app.AppCompatActivity
10+
import android.view.View
1011
import android.widget.Toast
1112
import com.mapbox.android.core.permissions.PermissionsManager
1213
import com.mapbox.api.directions.v5.models.DirectionsRoute
@@ -15,6 +16,7 @@ import com.mapbox.geojson.Point
1516
import com.mapbox.mapboxsdk.camera.CameraUpdate
1617
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory
1718
import com.mapbox.mapboxsdk.geometry.LatLngBounds
19+
import com.mapbox.mapboxsdk.maps.AttributionDialogManager
1820
import com.mapbox.mapboxsdk.maps.MapboxMap
1921
import com.mapbox.services.android.navigation.testapp.NavigationSettingsActivity
2022
import com.mapbox.services.android.navigation.testapp.R
@@ -35,7 +37,7 @@ class ExampleActivity : AppCompatActivity(), ExampleView {
3537

3638
companion object {
3739
const val ZERO_PADDING = 0
38-
const val BOTTOMSHEET_MULTIPLER = 4
40+
const val BOTTOMSHEET_MULTIPLIER = 4
3941
}
4042

4143
override fun onCreate(savedInstanceState: Bundle?) {
@@ -82,6 +84,13 @@ class ExampleActivity : AppCompatActivity(), ExampleView {
8284
presenter.onDestroy()
8385
}
8486

87+
override fun onBackPressed() {
88+
val exitActivity = presenter.onBackPressed()
89+
if (exitActivity) {
90+
super.onBackPressed()
91+
}
92+
}
93+
8594
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>,
8695
grantResults: IntArray) {
8796
permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults)
@@ -93,14 +102,19 @@ class ExampleActivity : AppCompatActivity(), ExampleView {
93102

94103
override fun onMapReady(mapboxMap: MapboxMap) {
95104
map = NavigationMapboxMap(mapView, mapboxMap)
96-
mapboxMap.addOnMapLongClickListener{ presenter.onMapLongClick(it) }
105+
map?.setOnRouteSelectionChangeListener(this)
106+
mapboxMap.addOnMapLongClickListener { presenter.onMapLongClick(it) }
97107
presenter.buildDynamicCameraFrom(mapboxMap)
98108
}
99109

100110
override fun onFeatureClicked(feature: CarmenFeature) {
101111
presenter.onDestinationFound(feature)
102112
}
103113

114+
override fun onNewPrimaryRouteSelected(directionsRoute: DirectionsRoute) {
115+
presenter.onNewRouteSelected(directionsRoute)
116+
}
117+
104118
override fun onPermissionResult(granted: Boolean) {
105119
presenter.onPermissionResult(granted)
106120
}
@@ -137,8 +151,8 @@ class ExampleActivity : AppCompatActivity(), ExampleView {
137151
map?.updateLocation(location)
138152
}
139153

140-
override fun updateRoute(route: DirectionsRoute) {
141-
map?.drawRoute(route)
154+
override fun updateRoutes(routes: List<DirectionsRoute>) {
155+
map?.drawRoutes(routes)
142156
}
143157

144158
override fun updateDestinationMarker(destination: Point) {
@@ -229,14 +243,20 @@ class ExampleActivity : AppCompatActivity(), ExampleView {
229243
override fun adjustMapPaddingForNavigation() {
230244
val mapViewHeight = mapView.height
231245
val bottomSheetHeight = resources.getDimension(R.dimen.bottom_sheet_peek_height).toInt()
232-
val topPadding = mapViewHeight - bottomSheetHeight * BOTTOMSHEET_MULTIPLER
246+
val topPadding = mapViewHeight - bottomSheetHeight * BOTTOMSHEET_MULTIPLIER
233247
map?.retrieveMap()?.setPadding(ZERO_PADDING, topPadding, ZERO_PADDING, ZERO_PADDING)
234248
}
235249

236250
override fun resetMapPadding() {
237251
map?.retrieveMap()?.setPadding(ZERO_PADDING, ZERO_PADDING, ZERO_PADDING, ZERO_PADDING)
238252
}
239253

254+
override fun showAttributionDialog(attributionView: View) {
255+
map?.retrieveMap()?.let {
256+
AttributionDialogManager(attributionView.context, it).onClick(attributionView)
257+
}
258+
}
259+
240260
private fun setupWith(savedInstanceState: Bundle?) {
241261
val viewModel = ViewModelProviders.of(this).get(ExampleViewModel::class.java)
242262
presenter = ExamplePresenter(this, viewModel)
@@ -258,15 +278,9 @@ class ExampleActivity : AppCompatActivity(), ExampleView {
258278
directionsFab.setOnClickListener { presenter.onDirectionsFabClick() }
259279
navigationFab.setOnClickListener { presenter.onNavigationFabClick() }
260280
cancelFab.setOnClickListener { presenter.onCancelFabClick() }
281+
attribution.setOnClickListener { presenter.onAttributionsClick(it) }
261282

262283
val granted = PermissionsManager.areLocationPermissionsGranted(this)
263284
presenter.onPermissionResult(granted)
264285
}
265-
266-
override fun onBackPressed() {
267-
val exitActivity = presenter.onBackPressed()
268-
if (exitActivity) {
269-
super.onBackPressed()
270-
}
271-
}
272286
}

app/src/main/java/com/mapbox/services/android/navigation/testapp/example/ui/ExamplePresenter.kt

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.arch.lifecycle.LifecycleOwner
44
import android.arch.lifecycle.Observer
55
import android.location.Location
66
import android.support.design.widget.BottomSheetBehavior
7+
import android.view.View
78
import android.view.View.INVISIBLE
89
import android.view.View.VISIBLE
910
import com.mapbox.api.directions.v5.models.DirectionsRoute
@@ -17,13 +18,11 @@ import com.mapbox.mapboxsdk.geometry.LatLngBounds
1718
import com.mapbox.mapboxsdk.maps.MapboxMap
1819
import com.mapbox.services.android.navigation.testapp.NavigationApplication
1920
import com.mapbox.services.android.navigation.testapp.R
20-
import com.mapbox.services.android.navigation.testapp.example.ui.offline.OfflineFilesLoadedCallback
2121
import com.mapbox.services.android.navigation.testapp.example.utils.formatArrivalTime
2222
import com.mapbox.services.android.navigation.ui.v5.camera.DynamicCamera
2323
import com.mapbox.services.android.navigation.v5.milestone.BannerInstructionMilestone
2424
import com.mapbox.services.android.navigation.v5.milestone.Milestone
2525
import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress
26-
import timber.log.Timber
2726
import kotlin.math.roundToInt
2827

2928
class ExamplePresenter(private val view: ExampleView, private val viewModel: ExampleViewModel) {
@@ -37,11 +36,6 @@ class ExamplePresenter(private val view: ExampleView, private val viewModel: Exa
3736
}
3837

3938
private var state: PresenterState = PresenterState.SHOW_LOCATION
40-
private val offlineCallback = object : OfflineFilesLoadedCallback {
41-
override fun onFilesLoaded() {
42-
Timber.d("Offline files loaded")
43-
}
44-
}
4539

4640
fun onPermissionResult(granted: Boolean) {
4741
if (granted) {
@@ -59,6 +53,10 @@ class ExamplePresenter(private val view: ExampleView, private val viewModel: Exa
5953
view.updateAutocompleteBottomSheetState(BottomSheetBehavior.STATE_EXPANDED)
6054
}
6155

56+
fun onAttributionsClick(attributionView: View) {
57+
view.showAttributionDialog(attributionView)
58+
}
59+
6260
fun onSettingsFabClick() {
6361
view.showSettings()
6462
}
@@ -75,16 +73,16 @@ class ExamplePresenter(private val view: ExampleView, private val viewModel: Exa
7573
}
7674

7775
fun onNavigationFabClick() {
78-
viewModel.route.value?.let {
76+
if (viewModel.canNavigate()) {
7977
state = PresenterState.NAVIGATE
8078
view.addMapProgressChangeListener(viewModel.retrieveNavigation())
81-
viewModel.startNavigationWith(it)
8279
view.updateNavigationFabVisibility(INVISIBLE)
8380
view.updateCancelFabVisibility(VISIBLE)
8481
view.updateNavigationDataVisibility(VISIBLE)
8582
view.updateAutocompleteBottomSheetHideable(true)
8683
view.updateAutocompleteBottomSheetState(BottomSheetBehavior.STATE_HIDDEN)
8784
view.adjustMapPaddingForNavigation()
85+
viewModel.startNavigation()
8886
}
8987
}
9088

@@ -143,20 +141,20 @@ class ExamplePresenter(private val view: ExampleView, private val viewModel: Exa
143141
}
144142
}
145143

146-
fun onRouteFound(route: DirectionsRoute?) {
147-
route?.let { directionsRoute ->
144+
fun onRouteFound(routes: List<DirectionsRoute>?) {
145+
routes?.let { directionsRoutes ->
148146
when (state) {
149147
PresenterState.FIND_ROUTE -> {
150148
state = PresenterState.ROUTE_FOUND
151-
view.updateRoute(directionsRoute)
149+
view.updateRoutes(directionsRoutes)
152150
view.updateDirectionsFabVisibility(INVISIBLE)
153151
view.updateNavigationFabVisibility(VISIBLE)
154152
viewModel.destination.value?.let { destination ->
155153
moveCameraToInclude(destination)
156154
}
157155
}
158156
PresenterState.NAVIGATE -> {
159-
viewModel.startNavigationWith(directionsRoute)
157+
view.updateRoutes(directionsRoutes)
160158
}
161159
else -> {
162160
// TODO no impl
@@ -165,6 +163,13 @@ class ExamplePresenter(private val view: ExampleView, private val viewModel: Exa
165163
}
166164
}
167165

166+
fun onNewRouteSelected(directionsRoute: DirectionsRoute) {
167+
viewModel.updatePrimaryRoute(directionsRoute)
168+
if (state == PresenterState.NAVIGATE) {
169+
viewModel.startNavigation()
170+
}
171+
}
172+
168173
fun onProgressUpdate(progress: RouteProgress?) {
169174
progress?.let {
170175
view.updateArrivalTime(it.formatArrivalTime(NavigationApplication.instance))
@@ -174,9 +179,9 @@ class ExamplePresenter(private val view: ExampleView, private val viewModel: Exa
174179
}
175180

176181
fun onMapLongClick(point: LatLng) {
177-
viewModel.reverseGeocode(point);
182+
viewModel.reverseGeocode(point)
178183
}
179-
184+
180185
fun onMilestoneUpdate(milestone: Milestone?) {
181186
milestone?.let {
182187
if (milestone is BannerInstructionMilestone) {
@@ -187,13 +192,21 @@ class ExamplePresenter(private val view: ExampleView, private val viewModel: Exa
187192
}
188193
}
189194

195+
fun onBackPressed(): Boolean {
196+
if (!viewModel.collapsedBottomSheet) {
197+
view.updateAutocompleteBottomSheetState(BottomSheetBehavior.STATE_COLLAPSED)
198+
return false
199+
}
200+
return true
201+
}
202+
190203
fun onDestroy() {
191204
viewModel.onDestroy()
192205
}
193206

194207
fun subscribe(owner: LifecycleOwner) {
195208
viewModel.location.observe(owner, Observer { onLocationUpdate(it) })
196-
viewModel.route.observe(owner, Observer { onRouteFound(it) })
209+
viewModel.routes.observe(owner, Observer { onRouteFound(it) })
197210
viewModel.progress.observe(owner, Observer { onProgressUpdate(it) })
198211
viewModel.milestone.observe(owner, Observer { onMilestoneUpdate(it) })
199212
viewModel.geocode.observe(owner, Observer {
@@ -202,7 +215,6 @@ class ExamplePresenter(private val view: ExampleView, private val viewModel: Exa
202215
}
203216
})
204217
viewModel.activateLocationEngine()
205-
viewModel.loadOfflineFiles(offlineCallback)
206218
}
207219

208220
fun buildDynamicCameraFrom(mapboxMap: MapboxMap) {
@@ -246,12 +258,4 @@ class ExamplePresenter(private val view: ExampleView, private val viewModel: Exa
246258
view.updateMapCameraFor(bounds, padding, TWO_SECONDS)
247259
}
248260
}
249-
250-
fun onBackPressed(): Boolean {
251-
if (!viewModel.collapsedBottomSheet) {
252-
view.updateAutocompleteBottomSheetState(BottomSheetBehavior.STATE_COLLAPSED)
253-
return false
254-
}
255-
return true
256-
}
257261
}

app/src/main/java/com/mapbox/services/android/navigation/testapp/example/ui/ExampleView.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
package com.mapbox.services.android.navigation.testapp.example.ui
22

33
import android.location.Location
4+
import android.view.View
45
import com.mapbox.android.core.permissions.PermissionsListener
56
import com.mapbox.android.search.autocomplete.OnFeatureClickListener
67
import com.mapbox.api.directions.v5.models.DirectionsRoute
78
import com.mapbox.geojson.Point
89
import com.mapbox.mapboxsdk.camera.CameraUpdate
910
import com.mapbox.mapboxsdk.geometry.LatLngBounds
1011
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback
12+
import com.mapbox.services.android.navigation.ui.v5.route.OnRouteSelectionChangeListener
1113
import com.mapbox.services.android.navigation.v5.navigation.MapboxNavigation
1214

13-
interface ExampleView: PermissionsListener, OnMapReadyCallback, OnFeatureClickListener {
15+
interface ExampleView: PermissionsListener, OnMapReadyCallback,
16+
OnFeatureClickListener, OnRouteSelectionChangeListener {
1417

1518
fun initialize()
1619

@@ -26,7 +29,7 @@ interface ExampleView: PermissionsListener, OnMapReadyCallback, OnFeatureClickLi
2629

2730
fun updateMapLocation(location: Location?)
2831

29-
fun updateRoute(route: DirectionsRoute)
32+
fun updateRoutes(routes: List<DirectionsRoute>)
3033

3134
fun updateDestinationMarker(destination: Point)
3235

@@ -69,4 +72,6 @@ interface ExampleView: PermissionsListener, OnMapReadyCallback, OnFeatureClickLi
6972
fun adjustMapPaddingForNavigation()
7073

7174
fun resetMapPadding()
75+
76+
fun showAttributionDialog(attributionView: View)
7277
}

0 commit comments

Comments
 (0)