Customize Drop-In UI
In the current iteration of Drop-In UI you can customize the default UI components in two mutually exclusive ways:
Style UI Components
To use a different set of colors and text properties, you can customize them in NavigationView
at runtime.
Add your custom style to styles.xml
or themes.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="MyCustomSpeedLimitStyle">
<item name="speedLimitTextColor">#FFFFFF</item>
<item name="speedLimitBackgroundColor">@color/primary</item>
<item name="speedLimitMutcdBorderColor">@color/secondary</item>
<item name="speedLimitViennaBorderColor">@color/secondary</item>
</style>
<style name="MyCustomSpeedLimitTextAppearance" parent="TextAppearance.AppCompat">
<item name="android:textSize">10sp</item>
<item name="android:textColor">#FFFFFF</item>
</style>
</resources>
In your Activity
or Fragment
invoke the function to change the appearance anytime
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.your_layout)
findViewById(R.id.navigationView).customizeViewStyles {
speedLimitStyle = R.style.MyCustomSpeedLimitStyle
speedLimitTextAppearance = R.style.MyCustomSpeedLimitTextAppearance
}
}
The snippet above shows how to customize speed limit UI component. To customize all the standalone UI components refer to the example below.
Render custom runtime styling of default UI components to be used with the NavigationView
NavigationViewOptions
NavigationView
exposes options that can be used to define the behavior of the components associated with it.
To change the appearance of route arrows, define RouteArrowOptions
and apply it to NavigationView
class MyActivity: AppCompatActivity() {
private val routeArrowOptions by lazy {
RouteArrowOptions.Builder(this)
.withAboveLayerId(RouteLayerConstants.TOP_LEVEL_ROUTE_LINE_LAYER_ID)
.withArrowColor(Color.RED)
.build()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.your_activity_layout)
findViewById(R.id.navigationView).customizeViewOptions {
routeArrowOptions = this@MyActivity.routeArrowOptions
}
}
}
NavigationViewOptions
only allows for defining RouteLine
, RouteArrow
, and selection of predefined map day and night styles as options. Support for a wide selection of customization options when using the NavigationView
is coming soon.
Apply NavigationViewOptions
at runtime.
Use custom views
To use a custom designed view with NavigationView
instead of the default supported view
Define the layout for custom view
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:parentTag="android.widget.FrameLayout">
<TextView
android:id="@+id/speedLimit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:textSize="18sp"
android:textColor="@android:color/black"
android:gravity="center"
android:background="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toStartOf="parent"/>
</merge>
Drop-In UI uses FrameLayout
as a container to display views on top of the MapView
. All default and custom views are merged into the parent FrameLayout
each of which has a specific bound set on the screen. For a better understanding of the bounds take a look at mapbox_navigation_view_layout
Create a UIBinder
UIBinder
is an interface responsible for transitioning view(s) into ViewGroup
@OptIn(ExperimentalPreviewMapboxNavigationAPI::class)
private class MySpeedLimitViewBinder : UIBinder {
override fun bind(viewGroup: ViewGroup): MapboxNavigationObserver {
val scene = Scene.getSceneForLayout(
viewGroup,
R.layout.my_speed_limit_layout,
viewGroup.context
)
TransitionManager.go(scene, Fade())
val binding = MySpeedLimitLayoutBinding.bind(viewGroup)
return MySpeedLimitComponent(binding)
}
}
The function bind
defines the transition of speed limit view into the viewGroup
using a Fade
transition. You can choose a different transition based on app requirements.
Create a UIComponent
UIComponent
is an interface that gives you access to MapboxNavigation
and coroutineScope
. onAttached
and onDetached
are invoked when the UIComponent
is attached to and detached from the binder. All coroutines that you launch in onAttached
are cancelled automatically when the observer is detached. Hence, you don't have to explicitly override onDetached
in your custom UIComponent
class MySpeedLimitComponent(
private val speedLimit: MySpeedLimitLayoutBinding
) : UIComponent() {
override fun onAttached(mapboxNavigation: MapboxNavigation) {
super.onAttached(mapboxNavigation)
mapboxNavigation.flowLocationMatcherResult().collect {
val postedSpeedLimit = it.speedLimit?.speedKmph
textView.text = when {
postedSpeedLimit != null -> "Speed Limit\n $postedSpeedLimit"
else -> "--"
}
}
}
}
Finally, apply your custom view binder to NavigationView
class MyActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.your_activity_layout)
findViewById(R.id.navigationView).customizeViewBinders {
speedLimitBinder = MySpeedLimitViewBinder()
}
}
}
Default speed limit | Custom speed limit |
---|---|
Render custom speed limit view to be used with the NavigationView