I am having problems with Button sizing on my screen. I want the buttons to be sized the same and to optimize the space I have. I tried to use spacers and Modifier.weight doesn't seem to be available anymore.
@Composable
fun ActionButton(ButtonText: String, ButtonColor: Color,) {
Button(
onClick = { /*TODO*/ },
enabled = true,
colors = ButtonColors(
containerColor = ButtonColor,
contentColor = Color.White,
disabledContainerColor = Color.Gray, //TODO: Look into this later
disabledContentColor = Color.LightGray
),
modifier = Modifier
.fillMaxWidth()
.padding(18.dp)
) {
Text(
text = ButtonText,
style = MaterialTheme.typography.displaySmall)
}
}
data class ActionButtonData(val ButtonText: String, val ButtonColor: Color)
@Composable
fun ActionButtonColumn(){
val ActionButtonsValues = listOf(
ActionButtonData("Call 911", MaterialTheme.colorScheme.primary),
ActionButtonData("Text 911", MaterialTheme.colorScheme.secondary),
ActionButtonData("SOS", MaterialTheme.colorScheme.tertiary)
)
Column (
horizontalAlignment = androidx.compose.ui.Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxSize()
) {
ActionButtonsValues.forEach {
ActionButton(ButtonText = it.ButtonText, ButtonColor = it.ButtonColor)
}
}
}
The reason why the weight
modifier cannot be used in the definition of ActionButton
is because it can only be used in scope of a column or row, thus it can't be used in a function because Compose doesn't "know" for sure whether the buttons will always be in or out of the column scope. You can find out by hovering your cursor over each use of Modifier.weight
in your code.
Consider the following example (a simplified version of your ActionButton
definition):
Button(
onClick = { ... },
modifier = modifier
.fillMaxWidth()
.weight(0.5f) // <-- not in a column
) { ... }
Here Android Studio will highlight an error, and when you hover over the use of Modifier.weight
you should see the suggestion “Create extension function androidx.compose.ui.Modifier.weight”
.
In contrast, in this case:
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxSize()
) {
Button(modifier = Modifier.weight(1f))
}
There is no problem with using the weight modifier as we're operating in the column scope. You can make sure of that by hovering your cursor over the usage of Modifier.weight
- you will see androidx.compose.foundation.layout.ColumnScope
.
Now that we've clarified what the column scope is all about - how do we actually solve this problem? We can't just move the column "context" to the ActionButton
definition, right?
Of course we can.
The nice and simple way to ensure a specific size of elements in a column (even if they're wrapped in another function) is to add another parameter to the function definition, like this:
@Composable
fun ActionButton(buttonText: String, modifier: Modifier)
(PS: notice I've also changed the signature of buttonText
as local variables shouldn't start with uppercase letters, it's typical for classes - best practice for the future :))
We also need to replace the original Modifier
in the function body with the new one:
Button(
onClick = { ... },
modifier = modifier // <-- not "Modifier"
.fillMaxWidth()
.padding(18.dp)
) {
Text(buttonText)
}
As you may have guessed, to pass the weight information to the single ActionButton
we will just put it as an argument:
actionButtonsValues.forEach {
ActionButton(
buttonText = it.buttonText,
modifier = Modifier.weight(1f)
)
}
This way, you can not only set all buttons to equal size, but also add a weight
field to ActionButtonData
and make some buttons bigger than the others. You can find more about it here.