Search Card customization
The content of the card is divided into functional blocks, and you can asynchronously hide or modify these blocks (green blocks on the image) in a stream like what is available in Kotlin Flow.
For constructing the card content, the following builder class is used:
class Builder {
private var arrivalInformation: ViewBlock = DefaultViewBlock
private var weather: ViewBlock = DefaultViewBlock
private var rating: ViewBlock = DefaultViewBlock
private var openHours: ViewBlock = DefaultViewBlock
private var chargingInformation: ViewBlock = DefaultViewBlock
private var destinationInformation: ViewBlock = DefaultViewBlock
private var destinationFeedback: ViewBlock = DefaultViewBlock
private val orderedViews: MutableMap<Int, ViewBlock> = mutableMapOf()
}
ViewBlock
is an abstract class with several implementations:
HiddenViewBlock
: This block remains hidden.DefaultViewBlock
: Default UI will be used.AndroidViewBlock
: Creates a view based on View.ComposeViewBlock
: Creates a view based on @Composable function.LoadingViewBlock
: This block can be used to display a loading indicator while the content is being fetched.
Customization Process
Customization is available through the DashLayoutEditor
class, which can be accessed via DashMainFragment
using the layoutEditor
method.
fragment.layoutEditor {
// logic for UI customization
}
DashLayoutEditor
provides two methods for customization:
updateDestinationPreviewLayout
: Updates the destination preview layout using the provided modification block.defaultDestinationPreviewLayout
: Resets the destination preview layout to its default state.
updateDestinationPreviewLayout
uses block: suspend CollectorBuilder.(DestinationResult) -> Unit
as a modification block where CollectorBuilder
is a helper class for creating DestinationPreviewLayout.Builder
in a simplified DSL format.
interface CollectorBuilder {
/**
* Assigns the DestinationPreviewLayout using the provided modification block.
*/
suspend infix fun assign(block: suspend DestinationPreviewLayout.Builder.() -> Unit)
/**
* Assigns the DestinationPreviewLayout using the default settings.
*/
suspend fun assignDefault()
}
CollectorBuilder
uses DestinationResult
as input to fill UI state.
Example Usage
private suspend fun DashNavigationFragment.setSingleCustomView() = editLayout {
updateDestinationPreviewLayout { destinationResult ->
// Set loading state
assign {
arrivalInformation(LoadingViewBlock)
destinationInformation(LoadingViewBlock)
}
// Call suspend function
val isCustomUiRequired = checkIfUiRequired(destinationResult)
if (isCustomUiRequired) {
assign {
custom(
DestinationPreviewLayout.Order.Weather,
DestinationPreviewLayout.RelativePosition.Below,
AndroidViewBlock(factory = { context -> AppCompatTextView(context) }) { view ->
view.text = "Show custom loading"
for (i in 1..20) {
delay(50) // Simulate loading via coroutine delay
view.text = "Loading${".".repeat(i)}"
}
view.text = "Custom view is loaded"
},
)
}
} else {
assignDefault()
}
}
}