7

I am a new in jetpack compose and I really wanted to know how I can dismiss a composable dialog. Is there any function like dismiss() for dialog in jetpack compose?

By using below code, I cannot dismiss the dialog either touching outside or pressing back button. The dialog just still is visible on the top of view hierarchy. `

@Composable
fun InfoDialog() {
    val shouldDismiss = remember {
        mutableStateOf(false)
    }
    Dialog(onDismissRequest = {
        shouldDismiss.value = false
    }, properties = DialogProperties(
        dismissOnBackPress = true,
        dismissOnClickOutside = true
    )) {
        Card(
            shape = RoundedCornerShape(8.dp),
            modifier = Modifier.padding(16.dp,8.dp,16.dp,8.dp),
            elevation = 8.dp
        ) {
            Column(
                Modifier.background(c282534)) {
                Column(modifier = Modifier.padding(16.dp)) {
                    Text(
                        text = "Notice",
                        textAlign = TextAlign.Center,
                        modifier = Modifier
                            .padding(top = 8.dp)
                            .fillMaxWidth(),
                        style = TextStyle(fontWeight = FontWeight.Bold, color = Color.White, fontSize = 24.sp),
                        maxLines = 2,
                        overflow = TextOverflow.Ellipsis
                    )
                    Text(
                        text = "Allow Permission to send you notifications when important update added.",
                        textAlign = TextAlign.Center,
                        modifier = Modifier
                            .padding(top = 8.dp, start = 24.dp, end = 24.dp)
                            .fillMaxWidth(),
                        style = TextStyle(color = Color.White, fontSize = 16.sp)
                    )
                }
                Row(
                    Modifier
                        .fillMaxWidth()
                        .padding(top = 8.dp),
                    horizontalArrangement = Arrangement.SpaceAround) {

                    TextButton(onClick = {
                        shouldDismiss.value = true
                    }, modifier = Modifier.weight(1f)) {

                        Text(
                            "Close",
                            fontWeight = FontWeight.Normal,
                            color = Color.White,
                            modifier = Modifier.padding(top = 8.dp, bottom = 8.dp)
                        )
                    }
                    TextButton(
                        onClick = {
                        shouldDismiss.value = true
                        },
                        modifier = Modifier.weight(1f)
                    ) {
                        Text(
                            "Allow",
                            fontWeight = FontWeight.ExtraBold,
                            color = Color.White,
                            modifier = Modifier.padding(top = 8.dp, bottom = 8.dp)
                        )
                    }
                }
            }
        }
    }
}

`

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841

2 Answers2

5

First, you should setup onDismissRequest, I guess in your case it will be shouldDismiss.value = true. Then you should hide Dialog based on shouldDismiss value. In order to hide you should just stop invoking Dialog {... function in your code based on condition. E.g. by adding fast return if (shouldDismiss.value) return. Finally it will look like this:

@Composable
fun InfoDialog() {
    val shouldDismiss = remember {
        mutableStateOf(false)
    }

    if (shouldDismiss.value) return
 
    Dialog(onDismissRequest = {
        shouldDismiss.value = true
    }, properties = DialogProperties(
        dismissOnBackPress = true,
        dismissOnClickOutside = true
    )) {
        Card(
            shape = RoundedCornerShape(8.dp),
            modifier = Modifier.padding(16.dp,8.dp,16.dp,8.dp),
            elevation = 8.dp
        ) {
            Column(
                Modifier.background(c282534)) {
                Column(modifier = Modifier.padding(16.dp)) {
                    Text(
                        text = "Notice",
                        textAlign = TextAlign.Center,
                        modifier = Modifier
                            .padding(top = 8.dp)
                            .fillMaxWidth(),
                        style = TextStyle(fontWeight = FontWeight.Bold, color = Color.White, fontSize = 24.sp),
                        maxLines = 2,
                        overflow = TextOverflow.Ellipsis
                    )
                    Text(
                        text = "Allow Permission to send you notifications when important update added.",
                        textAlign = TextAlign.Center,
                        modifier = Modifier
                            .padding(top = 8.dp, start = 24.dp, end = 24.dp)
                            .fillMaxWidth(),
                        style = TextStyle(color = Color.White, fontSize = 16.sp)
                    )
                }
                Row(
                    Modifier
                        .fillMaxWidth()
                        .padding(top = 8.dp),
                    horizontalArrangement = Arrangement.SpaceAround) {

                    TextButton(onClick = {
                        shouldDismiss.value = true
                    }, modifier = Modifier.weight(1f)) {

                        Text(
                            "Close",
                            fontWeight = FontWeight.Normal,
                            color = Color.White,
                            modifier = Modifier.padding(top = 8.dp, bottom = 8.dp)
                        )
                    }
                    TextButton(
                        onClick = {
                        shouldDismiss.value = true
                        },
                        modifier = Modifier.weight(1f)
                    ) {
                        Text(
                            "Allow",
                            fontWeight = FontWeight.ExtraBold,
                            color = Color.White,
                            modifier = Modifier.padding(top = 8.dp, bottom = 8.dp)
                        )
                    }
                }
            }
        }
    }
}

Evgeny K
  • 1,744
  • 3
  • 13
  • 19
  • Hmm so the dialog is just still there and I would hide it by adjust its alpha (opacity). Is it right? – Thái Quốc Toàn Nov 20 '22 at 09:26
  • no, compose function invokes each time your state changes, I added `if (shouldDismiss.value) return` in order to skip render Dialog if `shouldDismiss.value == true`. That's how it works, you just don't invoke `Dialog {...` based on some condition – Evgeny K Nov 20 '22 at 09:32
  • also you can use kotlin delegate sintax: `val shouldDismiss by remember { ` then you don't have to use `shouldDismiss.value` and just use `shouldDismiss` intead – Evgeny K Nov 20 '22 at 09:34
  • Is there any way to let the dialog disappear? As you see that in my question, I got the problem that the dialog has not disappear either touching outside or pressing back button – Thái Quốc Toàn Nov 20 '22 at 09:41
  • when user touches outside or pressing back button, Dialog's `onDismissRequest` is triggered and `shouldDismiss` state changes, then Compose reinvoke `InfoDialog` composable function and if `Dialog inside` is not invoked then it disappear = dismissed (if you want you can even animate this) – Evgeny K Nov 20 '22 at 09:45
  • You just bring me out of my mess. Also thank you for the useful suggestions. Happy coding! – Thái Quốc Toàn Nov 20 '22 at 10:04
2

The dialog is visible as long as it is part of the composition hierarchy. You should use something like:

val shouldShowDialog = remember { mutableStateOf(true) }

if (shouldShowDialog.value) {

    Dialog(onDismissRequest = { shouldShowDialog.value = false }) {            
        Button(onClick = {shouldShowDialog.value = false}){
                Text("Close")
        }
    }
}

Setting shouldShowDialog to false dismisses the Dialog. And to show just set shouldShowDialog to true. Something like:

Button(onClick = {shouldShowDialog.value = true}){
    Text("Open")
}
donturner
  • 17,867
  • 8
  • 59
  • 81
Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
  • Well, I've got the idea. Dismissing is not equal to remove it from view hierarchy. Thanks in advanced – Thái Quốc Toàn Nov 20 '22 at 09:33
  • @TháiQuốcToàn It is not correct. `openDialog` is a state. This is due to how composition and recomposition work in Compose. A value computed by `remember` is stored in the Composition during initial composition. Any changes to value will schedule recomposition of any composable functions that read that `value`. – Gabriele Mariotti Nov 20 '22 at 09:38
  • It the example it is not the `else` statement. The Dialog is in the hierarchy depending on the `if (openDialog.value)`. To dismiss the Dialog you have to set the `openDialog` to `false`. – Gabriele Mariotti Nov 20 '22 at 09:51
  • 1
    I do now get the idea. Really sorry for my bad comment so I deleted it. Again I appreciate your help! – Thái Quốc Toàn Nov 20 '22 at 10:01