Billy Newman
12/15/2021, 3:54 PMBilly Newman
12/15/2021, 3:55 PM@Composable
fun Content(someComposable: (@Composable () -> Unit)? = null) {
val background = someComposable?.background() // This does not work
}
Kirill Grouchnikov
12/15/2021, 4:14 PMsomeComposable
is not a view / container / component in the traditional sense. It may emit one UI component, it may emit more than one, or it may not emit anything.Billy Newman
12/15/2021, 4:17 PMinterface CustomScope {
@Stable
fun Modifier.background(background: Color): Modifier
}
@Composable
fun Content(someComposable: (@Composable CustomScope.() -> Unit)? = null) {
...
}
Adam Powell
12/15/2021, 4:19 PMAdam Powell
12/15/2021, 4:21 PMBilly Newman
12/15/2021, 4:43 PM@Composable
fun CommonContent(header: (@Composable () -> Unit)? = null) {
DragHandle()
header?.invoke()
}
@Composable
fun CustomContent() {
CommonContent() {
// custom header
Column(Modifier.background(Color.Blue)) { ... }
}
}
I would like for the drag handle view to have the same background color as the custom header. And I don’t really want to duplicate code. IE in this case a drag handle is “common” and should always be present regardless of the custom header.Casey Brooks
12/15/2021, 4:57 PMCommonContent
, you can use CompositionLocals to implicitly pass parameters down through the composition tree https://developer.android.com/jetpack/compose/compositionlocalChris Sinco [G]
12/15/2021, 5:04 PMMaterialTheme
like MaterialTheme.colors.background
can be useful here because from the code POV you are using a semantic color key, but can use CompositionLocal to override in specific parts in the hierarchy if needed.Chris Sinco [G]
12/15/2021, 5:05 PMBilly Newman
12/15/2021, 5:11 PM@Composable
fun CommonContent(
header: (@Composable () -> Unit)? = null,
headerColor: Color = Color.White
) {
DragHandle(headerColor)
header?.invoke()
}
But where does that end. Passing in every attribute the drag handle would have in common with the header component seems excessive.Billy Newman
12/15/2021, 5:12 PMBilly Newman
12/15/2021, 5:13 PMinterface ParentDataModifier : Modifier.Element {
/**
* Provides a parentData, given the [parentData] already provided through the modifier's chain.
*/
fun Density.modifyParentData(parentData: Any?): Any?
}
To allow the child to modify something on the parent right? Seems like exactly what I am trying to do.Chris Sinco [G]
12/15/2021, 5:17 PMNot really sure I want to pass parameters “down”Right, this is where CompositionLocals can be useful as it passes things down in the hierarchy, and it works particularly well for color overrides at certain parts of a UI hierarchy
Casey Brooks
12/15/2021, 5:20 PMval LocalHeaderColor = compositionLocalOf { Color.Unspecified }
@Composable
fun CommonContent(
header: (@Composable () -> Unit)? = null,
headerColor: Color = Color.White
) {
CompositionLocalProvider(LocalHeaderColor provides headerColor) {
DragHandle()
header?.invoke()
}
}
The content of both DragHandle
and the header
lambda can then reference the configured header color with LocalHeaderColor.current
, without having to pass it explicitly through function parametersBilly Newman
12/15/2021, 6:32 PMChris Sinco [G]
12/15/2021, 6:38 PMAdam Powell
12/15/2021, 6:45 PM