Last active
January 7, 2022 11:31
-
-
Save grandstaish/9eec95d879eb754cb5109caa49822dce to your computer and use it in GitHub Desktop.
*Very* rough POC for what one of our common components at Monzo could look like in Compose
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Composable | |
@OptIn(ExperimentalSubcomposeLayoutApi::class) | |
fun ListSection( | |
modifier: Modifier = Modifier, | |
header: String? = null, | |
footer: String? = null, | |
showDividers: Boolean = true, | |
dividerInset: Dp = 16.dp, | |
content: @Composable () -> Unit, | |
) { | |
Column(modifier = modifier) { | |
if (header != null) { | |
Text( | |
modifier = Modifier.padding(top = 8.dp), | |
text = header, | |
style = MaterialTheme.typography.caption, | |
) | |
} | |
Surface( | |
color = MaterialTheme.colors.secondary, | |
shape = MaterialTheme.shapes.medium | |
) { | |
SubcomposeLayout<ListSectionSlots>(Modifier.fillMaxWidth()) { constraints -> | |
val sectionWidth = constraints.maxWidth | |
val itemMeasureables = subcompose(ListSectionSlots.Items, content) | |
val itemPlaceables = itemMeasureables.fastMap { it.measure(constraints) } | |
val sectionHeight = itemPlaceables.fastSumBy { it.height } | |
val dividerCount = if (showDividers) itemPlaceables.size - 1 else 0 | |
val dividerMeasureables = subcompose(ListSectionSlots.Dividers) { | |
for (i in 0 until dividerCount) { | |
Divider(startIndent = dividerInset) | |
} | |
} | |
val dividerPlaceables = dividerMeasureables.fastMap { it.measure(constraints) } | |
layout(sectionWidth, sectionHeight) { | |
var y = 0 | |
itemPlaceables.fastForEachIndexed { index, placeable -> | |
placeable.placeRelative(0, y) | |
y += placeable.height | |
if (index < dividerCount) { | |
val dividerPlaceable = dividerPlaceables[index] | |
dividerPlaceable.placeRelative(0, y - dividerPlaceable.height / 2) | |
} | |
} | |
} | |
} | |
} | |
if (footer != null) { | |
Text( | |
text = footer, | |
style = MaterialTheme.typography.caption, | |
) | |
} | |
} | |
} | |
private enum class ListSectionSlots { | |
Items, | |
Dividers | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage:
Screenshot: