Skip to content

Commit 1dc164d

Browse files
[Drop-In UI] Ability to inject custom End Navigation button via Binder. (#6331)
* Introduced ViewBinderCustomization.infoPanelEndNavigationButtonBinder that allows injection of a custom Info Panel End Navigation Button. Updated InfoPanelHeaderActiveGuidanceBinder and InfoPanelHeaderArrivalBinder layouts, and binding logic to use infoPanelEndNavigationButtonBinder. Added InfoPanelEndNavigationButtonBinder that programmatically adds the End Navigation button. * CHANGELOG entry and QA-Test-App example.
1 parent a52f857 commit 1dc164d

17 files changed

Lines changed: 175 additions & 23 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Mapbox welcomes participation and contributions from everyone.
66
#### Features
77
- Added `ViewBinderCustomization.infoPanelHeaderFreeDriveBinder`, `ViewBinderCustomization.infoPanelHeaderDestinationPreviewBinder`, `ViewBinderCustomization.infoPanelHeaderRoutesPreviewBinder`, `ViewBinderCustomization.infoPanelHeaderActiveGuidanceBinder` and `ViewBinderCustomization.infoPanelHeaderArrivalBinder` that allows injection of a custom header content for each Navigation State in `NavigationView`. [#6273](https://github.com/mapbox/mapbox-navigation-android/pull/6273)
88
- Introduced `MapboxExtendableButtonParams` to allow end users to customize the default Drop-In UI buttons. [#6327](https://github.com/mapbox/mapbox-navigation-android/pull/6327)
9+
- Added `ViewBinderCustomization.infoPanelEndNavigationButtonBinder` that allows injection of a custom Info Panel End Navigation Button in `NavigationView`. [#6331](https://github.com/mapbox/mapbox-navigation-android/pull/6331)
910
#### Bug fixes and improvements
1011
- Optimized calls to modify route arrow layer visibility. [#6308](https://github.com/mapbox/mapbox-navigation-android/pull/6308)
1112
- Provide better java support for `MapboxNavigationApp`. [#6292](https://github.com/mapbox/mapbox-navigation-android/pull/6292)

libnavui-dropin/api/current.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ package com.mapbox.navigation.dropin {
116116
method public java.util.List<com.mapbox.navigation.dropin.ActionButtonDescription>? getCustomActionButtons();
117117
method public com.mapbox.navigation.dropin.binder.infopanel.InfoPanelBinder? getInfoPanelBinder();
118118
method public com.mapbox.navigation.ui.base.lifecycle.UIBinder? getInfoPanelContentBinder();
119+
method public com.mapbox.navigation.ui.base.lifecycle.UIBinder? getInfoPanelEndNavigationButtonBinder();
119120
method public com.mapbox.navigation.ui.base.lifecycle.UIBinder? getInfoPanelHeaderActiveGuidanceBinder();
120121
method public com.mapbox.navigation.ui.base.lifecycle.UIBinder? getInfoPanelHeaderArrivalBinder();
121122
method public com.mapbox.navigation.ui.base.lifecycle.UIBinder? getInfoPanelHeaderBinder();
@@ -132,6 +133,7 @@ package com.mapbox.navigation.dropin {
132133
method public void setCustomActionButtons(java.util.List<com.mapbox.navigation.dropin.ActionButtonDescription>?);
133134
method public void setInfoPanelBinder(com.mapbox.navigation.dropin.binder.infopanel.InfoPanelBinder?);
134135
method public void setInfoPanelContentBinder(com.mapbox.navigation.ui.base.lifecycle.UIBinder?);
136+
method public void setInfoPanelEndNavigationButtonBinder(com.mapbox.navigation.ui.base.lifecycle.UIBinder?);
135137
method public void setInfoPanelHeaderActiveGuidanceBinder(com.mapbox.navigation.ui.base.lifecycle.UIBinder?);
136138
method public void setInfoPanelHeaderArrivalBinder(com.mapbox.navigation.ui.base.lifecycle.UIBinder?);
137139
method public void setInfoPanelHeaderBinder(com.mapbox.navigation.ui.base.lifecycle.UIBinder?);
@@ -148,6 +150,7 @@ package com.mapbox.navigation.dropin {
148150
property public final java.util.List<com.mapbox.navigation.dropin.ActionButtonDescription>? customActionButtons;
149151
property public final com.mapbox.navigation.dropin.binder.infopanel.InfoPanelBinder? infoPanelBinder;
150152
property public final com.mapbox.navigation.ui.base.lifecycle.UIBinder? infoPanelContentBinder;
153+
property public final com.mapbox.navigation.ui.base.lifecycle.UIBinder? infoPanelEndNavigationButtonBinder;
151154
property public final com.mapbox.navigation.ui.base.lifecycle.UIBinder? infoPanelHeaderActiveGuidanceBinder;
152155
property public final com.mapbox.navigation.ui.base.lifecycle.UIBinder? infoPanelHeaderArrivalBinder;
153156
property public final com.mapbox.navigation.ui.base.lifecycle.UIBinder? infoPanelHeaderBinder;

libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/ViewBinder.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ internal class ViewBinder {
7777
val infoPanelTripProgressBinder: StateFlow<UIBinder?>
7878
get() = _infoPanelTripProgressBinder.asStateFlow()
7979

80+
private val _infoPanelEndNavigationButtonBinder: MutableStateFlow<UIBinder?> =
81+
MutableStateFlow(null)
82+
val infoPanelEndNavigationButtonBinder: StateFlow<UIBinder?>
83+
get() = _infoPanelEndNavigationButtonBinder.asStateFlow()
84+
8085
private val _infoPanelContentBinder: MutableStateFlow<UIBinder?> = MutableStateFlow(null)
8186
val infoPanelContentBinder: StateFlow<UIBinder?> get() = _infoPanelContentBinder.asStateFlow()
8287

@@ -111,6 +116,9 @@ internal class ViewBinder {
111116
_infoPanelTripProgressBinder.emitOrNull(it)
112117
}
113118
customization.infoPanelContentBinder?.also { _infoPanelContentBinder.emitOrNull(it) }
119+
customization.infoPanelEndNavigationButtonBinder?.also {
120+
_infoPanelEndNavigationButtonBinder.emitOrNull(it)
121+
}
114122
}
115123

116124
private fun <T : UIBinder> MutableStateFlow<T?>.emitOrNull(v: T) {

libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/ViewBinderCustomization.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ class ViewBinderCustomization {
8989
*/
9090
var infoPanelContentBinder: UIBinder? = null
9191

92+
/**
93+
* Customize the Info Panel End Navigation Button by providing your own [UIBinder].
94+
* Use [UIBinder.USE_DEFAULT] to reset to default.
95+
*/
96+
var infoPanelEndNavigationButtonBinder: UIBinder? = null
97+
9298
/**
9399
* Customize the Action Buttons by providing your own [UIBinder].
94100
* Use [UIBinder.USE_DEFAULT] to reset to default.

libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/ViewStyleCustomization.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,10 @@ class ViewStyleCustomization {
270270
*/
271271
fun defaultEndNavigationButtonParams(context: Context) = MapboxExtendableButtonParams(
272272
R.style.DropInStyleExitButton,
273-
context.defaultLayoutParams(),
273+
context.defaultLayoutParams().apply {
274+
marginEnd =
275+
context.resources.getDimensionPixelSize(R.dimen.mapbox_infoPanel_paddingEnd)
276+
},
274277
)
275278

276279
/**
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.mapbox.navigation.dropin.binder.infopanel
2+
3+
import android.view.ViewGroup
4+
import com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI
5+
import com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver
6+
import com.mapbox.navigation.dropin.NavigationViewContext
7+
import com.mapbox.navigation.dropin.component.infopanel.EndNavigationButtonComponent
8+
import com.mapbox.navigation.ui.base.lifecycle.UIBinder
9+
10+
@ExperimentalPreviewMapboxNavigationAPI
11+
internal class InfoPanelEndNavigationButtonBinder(
12+
private val context: NavigationViewContext
13+
) : UIBinder {
14+
15+
override fun bind(viewGroup: ViewGroup): MapboxNavigationObserver {
16+
return EndNavigationButtonComponent(
17+
context.store,
18+
viewGroup,
19+
context.styles.endNavigationButtonParams
20+
)
21+
}
22+
}

libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/binder/infopanel/InfoPanelHeaderActiveGuidanceBinder.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ internal class InfoPanelHeaderActiveGuidanceBinder(
3030
return context.run {
3131
navigationListOf(
3232
tripProgressComponent(binding.tripProgressLayout),
33-
endNavigationButtonComponent(binding.endNavigationContainer)
33+
endNavigationButtonComponent(binding.endNavigationButtonLayout)
3434
)
3535
}
3636
}

libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/binder/infopanel/InfoPanelHeaderArrivalBinder.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ internal class InfoPanelHeaderArrivalBinder(
3030
return context.run {
3131
navigationListOf(
3232
arrivalTextComponent(binding.arrivedText),
33-
endNavigationButtonComponent(binding.endNavigation)
33+
endNavigationButtonComponent(binding.endNavigationButtonLayout)
3434
)
3535
}
3636
}

libnavui-dropin/src/main/java/com/mapbox/navigation/dropin/internal/NavigationViewContextEx.kt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import androidx.appcompat.widget.AppCompatTextView
77
import com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI
88
import com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver
99
import com.mapbox.navigation.dropin.NavigationViewContext
10+
import com.mapbox.navigation.dropin.binder.infopanel.InfoPanelEndNavigationButtonBinder
1011
import com.mapbox.navigation.dropin.binder.infopanel.InfoPanelTripProgressBinder
1112
import com.mapbox.navigation.dropin.component.infopanel.ArrivalTextComponent
12-
import com.mapbox.navigation.dropin.component.infopanel.EndNavigationButtonComponent
1313
import com.mapbox.navigation.dropin.component.infopanel.POINameComponent
1414
import com.mapbox.navigation.dropin.component.infopanel.RoutePreviewButtonComponent
1515
import com.mapbox.navigation.dropin.component.infopanel.StartNavigationButtonComponent
@@ -29,8 +29,14 @@ internal fun NavigationViewContext.startNavigationButtonComponent(buttonContaine
2929
StartNavigationButtonComponent(store, buttonContainer, styles.startNavigationButtonParams)
3030

3131
@ExperimentalPreviewMapboxNavigationAPI
32-
internal fun NavigationViewContext.endNavigationButtonComponent(buttonContainer: ViewGroup) =
33-
EndNavigationButtonComponent(store, buttonContainer, styles.endNavigationButtonParams)
32+
internal fun NavigationViewContext.endNavigationButtonComponent(
33+
endNavigationButtonLayout: ViewGroup
34+
): MapboxNavigationObserver {
35+
val binderFlow = uiBinders.infoPanelEndNavigationButtonBinder.map {
36+
it ?: InfoPanelEndNavigationButtonBinder(this)
37+
}
38+
return reloadOnChange(binderFlow) { it.bind(endNavigationButtonLayout) }
39+
}
3440

3541
@ExperimentalPreviewMapboxNavigationAPI
3642
internal fun NavigationViewContext.arrivalTextComponent(textView: AppCompatTextView) =
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
@file:JvmName("MapboxExtendableButtonEx")
2+
package com.mapbox.navigation.dropin.internal.extensions
3+
4+
import android.content.res.Resources
5+
import androidx.annotation.StyleRes
6+
import com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI
7+
import com.mapbox.navigation.ui.base.view.MapboxExtendableButton
8+
import com.mapbox.navigation.utils.internal.logE
9+
10+
/**
11+
* Safely change the style of the receiver [MapboxExtendableButton].
12+
*
13+
* This method calls [MapboxExtendableButton.updateStyle] and captures [Resources.NotFoundException].
14+
*
15+
* @see [MapboxExtendableButton.updateStyle]
16+
*/
17+
@ExperimentalPreviewMapboxNavigationAPI
18+
internal fun MapboxExtendableButton.tryUpdateStyle(@StyleRes style: Int) {
19+
try {
20+
updateStyle(style)
21+
} catch (e: Resources.NotFoundException) {
22+
logE(
23+
"Failed to update style: ${e.localizedMessage}",
24+
"MapboxExtendableButton"
25+
)
26+
}
27+
}

0 commit comments

Comments
 (0)