Home > Software engineering >  How to make parent composable re-measure when a child appears dynamically?
How to make parent composable re-measure when a child appears dynamically?

Time:02-28

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))
}

CodePudding user response:

It looks like the topmost Dialog view size is not getting updated after the first recomposition. I believe it's a bug and I've reported it.

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
    }
}
  • Related