
In this article, we will learn how to work with Dialog and AlertDialog APIs in Jetpack Compose.
Prerequisites:
- State Management in Jetpack Compose
- Row, Column, and Box Layouts
- TextButton API with Examples
- Text API with Examples
This article talks about the Material 2 dialog APIs. If you want the latest Material 3 version, follow this link.
First, create an empty Jetpack Compose project and open MainActivity. Create a composable called MyUI() and call it from the onCreate(). We’ll write our code in it.
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
YourProjectNameTheme(darkTheme = false) {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
MyUI()
}
}
}
}
}
}
@Composable
fun MyUI() {
}
Jetpack Compose provides 2 Dialog APIs:
1. AlertDialog:
We can use it to make popup dialogs. Start typing AlertDialog and select the one with confirm and dismiss buttons.

It takes multiple parameters:
@Composable
fun AlertDialog(
onDismissRequest: () -> Unit,
confirmButton: @Composable () -> Unit,
modifier: Modifier = Modifier,
dismissButton: @Composable (() -> Unit)? = null,
title: @Composable (() -> Unit)? = null,
text: @Composable (() -> Unit)? = null,
shape: Shape = MaterialTheme.shapes.medium,
backgroundColor: Color = MaterialTheme.colors.surface,
contentColor: Color = contentColorFor(backgroundColor),
properties: DialogProperties = DialogProperties()
)
onDismissRequest – A lambda that is called when the user dismisses the dialog. It can be triggered when the user presses the back button or clicks outside the dialog. It is not called if you tap on the dismissButton.
confirmButton – A button for confirming an action. We use TextButton API.
modifier – To modify the layout of the dialog.
dismissButton – A button for dismissing the dialog. It is also a TextButton.
title – The title of the action. We add Text() composable here.
text – Description of the action. We also add Text() composable here.
shape – To set the shape for the dialog.
backgroundColor – The background color of the dialog.
contentColor – The dialog’s children’s preferred color.
properties – Additional configuration options.
Here is a simple example:
@Composable
fun MyUI() {
var dialogOpen by remember {
mutableStateOf(false)
}
if (dialogOpen) {
AlertDialog(
onDismissRequest = {
// Dismiss the dialog when the user clicks outside the dialog or on the back button.
// If you want to disable that functionality, simply leave this block empty.
dialogOpen = false
},
confirmButton = {
TextButton(
onClick = {
// perform the confirm action and
// close the dialog
dialogOpen = false
}
) {
Text(text = "Confirm")
}
},
dismissButton = {
TextButton(
onClick = {
// close the dialog
dialogOpen = false
}
) {
Text(text = "Dismiss")
}
},
title = {
Text(text = "Title")
},
text = {
Text(text = "Description")
},
modifier = Modifier
.fillMaxWidth()
.padding(32.dp),
shape = RoundedCornerShape(5.dp),
backgroundColor = Color.White
)
}
Button(
onClick = { dialogOpen = true }
) {
Text(text = "SHOW DIALOG")
}
}
Output:

By default, it places the buttons horizontally next to each other. There is another overload that provides the custom layout for the buttons. Start typing AlertDialog and select the one with the buttons parameter.

Example:
@Composable
fun MyUI() {
var dialogOpen by remember {
mutableStateOf(false)
}
if (dialogOpen) {
AlertDialog(
onDismissRequest = {
// Dismiss the dialog when the user clicks outside the dialog or on the back button.
// If you want to disable that functionality, simply leave this block empty.
dialogOpen = false
},
buttons = {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 24.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
// confirm button
Button(
onClick = {
dialogOpen = false
}
) {
Text(text = "Confirm")
}
// dismiss button
Button(
onClick = {
dialogOpen = false
}
) {
Text(text = "Dismiss")
}
}
},
title = {
Text(text = "Title")
},
text = {
Text(text = "Description")
},
modifier = Modifier
.fillMaxWidth()
.padding(32.dp),
shape = RoundedCornerShape(5.dp),
backgroundColor = Color.White
)
}
Button(onClick = { dialogOpen = true }) {
Text(text = "SHOW DIALOG")
}
}
Output:

2. Dialog:
The Dialog API provides the functionality to create custom dialogs.
@Composable
fun Dialog(
onDismissRequest: () -> Unit,
properties: DialogProperties = DialogProperties(),
content: @Composable () -> Unit
)
Example:
@Composable
fun MyUI() {
var dialogOpen by remember {
mutableStateOf(false)
}
if (dialogOpen) {
Dialog(onDismissRequest = {
dialogOpen = false
}) {
Surface(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight(),
shape = RoundedCornerShape(size = 10.dp)
) {
Column(modifier = Modifier.padding(all = 16.dp)) {
Text(text = "Your Dialog UI Here")
}
}
}
}
Button(onClick = { dialogOpen = true }) {
Text(text = "OPEN")
}
}
Output:

Related: Look at these awesome custom dialogs made with Jetpack Compose.
Dialog Properties:
The DialogProperties() helps us to further configure the dialog.
class DialogProperties constructor(
val dismissOnBackPress: Boolean = true,
val dismissOnClickOutside: Boolean = true,
val securePolicy: SecureFlagPolicy = SecureFlagPolicy.Inherit,
val usePlatformDefaultWidth: Boolean = true
)
dismissOnBackPress – If the dialog should be dismissed when the user presses the back button. If it is true, pressing the back button will call onDismissRequest.
dismissOnClickOutside – If the dialog should be dismissed when the user clicks outside the dialog. If it is true, clicking outside the dialog will call onDismissRequest.
securePolicy – Policy for setting FLAG_SECURE on the dialog’s window.
usePlatformDefaultWidth – If the dialog should use the platform’s default width which is smaller than the screen size. If you want to create a full screen dialog, set its value to false. This is experimental.
Both the AlertDialog() and Dialog() composables accept properties parameter. By default, the dialog will be dismissed when the user clicks outside of it. Let’s disable the functionality.
@Composable
fun MyUI() {
var dialogOpen by remember {
mutableStateOf(false)
}
if (dialogOpen) {
Dialog(
onDismissRequest = {
dialogOpen = false
},
properties = DialogProperties(
dismissOnClickOutside = false
)
) {
Surface(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight(),
shape = RoundedCornerShape(size = 10.dp)
) {
Column(modifier = Modifier.padding(all = 16.dp)) {
Text(text = "You cannot close me by clicking outside")
}
}
}
}
Button(onClick = { dialogOpen = true }) {
Text(text = "SHOW DIALOG")
}
}
Output:

Related Articles:
References:
I can’t thank you enough for this awesome and comprehensive tutorial. Thank you so much
Thank you 🙂