Hi I have simple case that I make visible buttons placed next to a TextField
in a Row
based on index. I observed that if I put buttons before TextField
in that row TextField
behaves as I'm expected and fills max width when possible. But if I put buttons after TextField
then TextField
always occupy max width and buttons never be visible. What is the reason for that, and what are the possible solutions ?
Thanks in advance.
Here is the reproducable code snippet and SS:
Case 1:
@Composable
fun UrlTextfield2(
modifier: Modifier = Modifier,
isPlusButtonVisible: Boolean,
isMinusButtonVisible: Boolean,
onClickPlusButton: () -> Unit,
onClickMinusButton: () -> Unit,
) {
Row(modifier = modifier.fillMaxWidth()) {
AnimatedVisibility(visible = isPlusButtonVisible) {
IconButton(onClick = onClickPlusButton, modifier = Modifier.fillMaxWidth(0.1f)) {
Icon(imageVector = Icons.Default.Add, contentDescription = "")
}
}
AnimatedVisibility(visible = isMinusButtonVisible) {
IconButton(onClick = onClickMinusButton, modifier = Modifier.fillMaxWidth(0.1f)) {
Icon(imageVector = Icons.Default.Close, contentDescription = "")
}
}
TextField(
value = "",
onValueChange = { },
modifier = Modifier.fillMaxWidth(),
label = { Text(text = "URL") },
)
}
}
Case 2:
@Composable
fun UrlTextfield2(
modifier: Modifier = Modifier,
isPlusButtonVisible: Boolean,
isMinusButtonVisible: Boolean,
onClickPlusButton: () -> Unit,
onClickMinusButton: () -> Unit,
) {
Row(modifier = modifier.fillMaxWidth()) {
TextField(
value = "",
onValueChange = { },
modifier = Modifier.fillMaxWidth(),
label = { Text(text = "URL") },
)
AnimatedVisibility(visible = isPlusButtonVisible) {
IconButton(onClick = onClickPlusButton, modifier = Modifier.fillMaxWidth(0.1f)) {
Icon(imageVector = Icons.Default.Add, contentDescription = "")
}
}
AnimatedVisibility(visible = isMinusButtonVisible) {
IconButton(onClick = onClickMinusButton, modifier = Modifier.fillMaxWidth(0.1f)) {
Icon(imageVector = Icons.Default.Close, contentDescription = "")
}
}
}
}
The issue isn't related to AnimatedVisibility
but to how the fillMaxWidth
modifier works.
In Case 1, the buttons are placed before the TextField
. The TextField
takes the remaining space with fillMaxWidth()
. This works as expected because the TextField
fills the remaining width after the buttons are placed.
In Case 2, the TextField
is placed before the buttons. Since the TextField
uses fillMaxWidth()
, it takes up all the available space, leaving no room for the buttons, which is why they never become visible.
To fix this, you can use the weight
modifier instead of fillMaxWidth
. The weight
modifier allows the TextField
to take up the remaining space after the buttons are given their specified width.
Here's the corrected code for both cases:
Case 1:
@Composable
fun UrlTextfield2(
modifier: Modifier = Modifier,
isPlusButtonVisible: Boolean,
isMinusButtonVisible: Boolean,
onClickPlusButton: () -> Unit,
onClickMinusButton: () -> Unit,
) {
Row(modifier = modifier.fillMaxWidth()) {
AnimatedVisibility(visible = isPlusButtonVisible) {
IconButton(onClick = onClickPlusButton, modifier = Modifier.fillMaxWidth(0.1f)) {
Icon(imageVector = Icons.Default.Add, contentDescription = "")
}
}
AnimatedVisibility(visible = isMinusButtonVisible) {
IconButton(onClick = onClickMinusButton, modifier = Modifier.fillMaxWidth(0.1f)) {
Icon(imageVector = Icons.Default.Close, contentDescription = "")
}
}
TextField(
value = "",
onValueChange = { },
modifier = Modifier.weight(1f),
label = { Text(text = "URL") },
)
}
}
Case 2:
@Composable
fun UrlTextfield2(
modifier: Modifier = Modifier,
isPlusButtonVisible: Boolean,
isMinusButtonVisible: Boolean,
onClickPlusButton: () -> Unit,
onClickMinusButton: () -> Unit,
) {
Row(modifier = modifier.fillMaxWidth()) {
TextField(
value = "",
onValueChange = { },
modifier = Modifier.weight(1f),
label = { Text(text = "URL") },
)
AnimatedVisibility(visible = isPlusButtonVisible) {
IconButton(onClick = onClickPlusButton, modifier = Modifier.fillMaxWidth(0.1f)) {
Icon(imageVector = Icons.Default.Add, contentDescription = "")
}
}
AnimatedVisibility(visible = isMinusButtonVisible) {
IconButton(onClick = onClickMinusButton, modifier = Modifier.fillMaxWidth(0.1f)) {
Icon(imageVector = Icons.Default.Close, contentDescription = "")
}
}
}
}