'How to make Dialog re-measure when a child size changes dynamically?
I implemented a simple dialog with Jetpack Compose on Android.
I am trying to show a caution message when isRehearsal
is true
.
The variable isRehearsal
is toggled when the user clicks buttons, and changing button works fine when the user clicks the buttons and toggles isRehearal
.
The problem is, that the caution text does not appear when the initial value of isRehearsal
is false
and later the variable becomes true
. When I change the initial value of isRehearsal
to true
, then the text disappears/appears fine when isRehearsal
becomes false
or true
.
var isRehearsal by remember { mutableStateOf(false) }
Dialog(
onDismissRequest = { dismiss() },
DialogProperties(dismissOnBackPress = true, dismissOnClickOutside = true)
) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.background(White, shape = RoundedCornerShape(8.dp))
.fillMaxWidth()
.padding(12.dp)
) { // the box does not resize when the caution text appears dynamically.
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
Text(text = "Set speed")
Row(
horizontalArrangement = Arrangement.SpaceEvenly,
modifier = Modifier.fillMaxWidth()
) {
if (isRehearsal) {
Button(
onClick = { isRehearsal = false },
colors = ButtonDefaults.buttonColors(
backgroundColor = Colors.Red400
)
) {
Text(text = "Rehearsal ON")
}
} else {
Button(
onClick = { isRehearsal = true },
colors = ButtonDefaults.buttonColors(
backgroundColor = Colors.Green400
)
) {
Text(text = "Rehearsal OFF")
}
}
Button(onClick = { onClickStart(pickerValue) }) {
Text(text = "Start")
}
}
if (isRehearsal) { // BUG!! when the intial value of isRehearsal is false, then the text never appears even when the value becomes true.
Text(text = "Rehearsal does not count as high score") // <- The caution text
}
}
}
}
How should I change the Box
block to make the box's height extend properly to be able to wrap caution text when a view appears dynamically?
Edit
If I change the catuion message part to like below, the text appears fine even when the initial value of isRehearsal
is false
. Therefore, I think that the issue is with the height of the Box
composable.
if (isRehearsal) {
Text(text = "Rehearsal does not count as high score")
} else {
Spacer(modifier = Modifier.height(100.dp))
}
Solution 1:[1]
It looks like the topmost Dialog
view size is not getting updated after the first recomposition. It's a known bug.
As a workaround until it's fixed, you can make a transparent topmost view take all the size available, and handle clicks same as dismissOnClickOutside
option does:
Dialog(
onDismissRequest = { },
) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.fillMaxSize()
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
) {
// same action as in onDismissRequest
}
) {
// content
}
}
Solution 2:[2]
You can use DialogProperties() with
usePlatformDefaultWidth = false
as a workaround. Example:
Dialog(
onDismissRequest = {},
properties = DialogProperties(usePlatformDefaultWidth = false)
) {
Card(modifier = Modifier.padding(8.dp).wrapContentSize().animateContentSize()) {
// content
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | adAAM91 |