mattinger
02/01/2023, 7:50 PM.weight(1.0f, true)
Then the outer column is occupying the entire space that its parent is allowing it to fill. This means i have to pass a variable to the “weight” function based on whether i want the element to occupy additional space or not. I’m using this inside of a modal bottom sheet and it’s making my bottom sheet occupy the entire height of the screen, when it doesn’t really need it. Code in 🧵mattinger
02/01/2023, 7:51 PM@Composable
fun StandardTemplateLayout(
modifier: Modifier = Modifier,
fullscreen: Boolean = true,
scrollState: ScrollState = rememberScrollState(),
media: @Composable ColumnScope.() -> Unit = { },
buttons: @Composable (ColumnScope.() -> Unit)? = null,
content: @Composable ColumnScope.() -> Unit,
) {
Column(
modifier = modifier
) {
Column(
modifier = Modifier
.testTag(TestTags.ScrollContainer)
.fillMaxWidth()
.weight(1.0f, fullscreen)
.verticalScroll(scrollState),
horizontalAlignment = Alignment.Start,
verticalArrangement = spacedBy(24.dp)
) {
...
}
buttons?.let {
Column(
modifier = Modifier.padding(
start = HorizontalPadding,
end = HorizontalPadding,
top = ButtonTopPadding,
bottom = ButtonBottomPadding,
)
) {
it()
}
}
}
}
mattinger
02/01/2023, 7:54 PMmattinger
02/01/2023, 7:54 PMDave Scheck
02/01/2023, 8:12 PMverticalArrangement = Arrangement.Bottom
and reverse the order of your inner elements. Have the buttons draw first and they should be at the bottom. Then your column should draw after it and take up the remaining space right?Dave Scheck
02/01/2023, 8:22 PMval fullScreen = remember { mutableStateOf(false)}
Column(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight()
.background(Color.Red),
verticalArrangement = Arrangement.Bottom
) {
Column(
modifier = Modifier
.fillMaxWidth()
.weight(1.0f, fullScreen.value)
.background(Color.Blue)
,
) {
Text("Test")
}
Row(modifier = Modifier.fillMaxWidth().background(Color.Yellow)) {
Button(onClick = {
fullScreen.value = !fullScreen.value
}) {Text("Button")}
}
}
I think this is the toggled behavior that you're looking for based on your flagAlex Vanyo
02/01/2023, 8:32 PMmattinger
02/01/2023, 8:35 PMAlex Vanyo
02/01/2023, 8:39 PMmattinger
02/01/2023, 10:11 PMmattinger
02/01/2023, 10:12 PMAlex Vanyo
02/01/2023, 10:15 PMColumn(Modifier.height(70.dp), verticalArrangement = BottomReversed) {
// This will take up space first and placed at the bottom, so it won't be cut off
Box(
Modifier
.background(Color.Red)
.size(32.dp))
// This will take up space third, if there is still space left over after
// the column reaches its intrinsic size, so that the scrollable column is
// pinned to the top
Spacer(Modifier.weight(1f))
// This will take up the remaining space second. If there isn't enough space,
// the column will become scrollable. The Column won't expand any further
// than it's intrinsic size
Column(Modifier.verticalScroll(rememberScrollState())) {
Box(
Modifier
.background(Color.Blue)
.size(32.dp))
Box(
Modifier
.background(Color.Green)
.size(32.dp))
}
}
Alex Vanyo
02/01/2023, 10:17 PMBottomReversed
is based on the built-in `Arrangement.Reversed`:
@Stable
val BottomReversed = object : Arrangement.Vertical {
override fun Density.arrange(
totalSize: Int,
sizes: IntArray,
outPositions: IntArray
) = placeRightOrBottom(totalSize, sizes, outPositions, reverseInput = true)
override fun toString() = "Arrangement#BottomReversed"
}
internal fun placeRightOrBottom(
totalSize: Int,
size: IntArray,
outPosition: IntArray,
reverseInput: Boolean
) {
val consumedSize = size.fold(0) { a, b -> a + b }
var current = totalSize - consumedSize
size.forEachIndexed(reverseInput) { index, it ->
outPosition[index] = current
current += it
}
}
private inline fun IntArray.forEachIndexed(reversed: Boolean, action: (Int, Int) -> Unit) {
if (!reversed) {
forEachIndexed(action)
} else {
for (i in (size - 1) downTo 0) {
action(i, get(i))
}
}
}