Create custom dialog in jetpack compose

In this tutorial, I am going to explain how to create a dialog in jetpack compose android in very simple steps. In this example, I have created multiple alert dialogs with different use cases.

let’s get started with creating a simple alert dialog creation.

To learn more about the jetpack compose check out my other tutorials on jetpack compose.

Getting started with jetpack compose – Basic components

Getting started with jetpack compose – Layouts

Getting started with jetpack compose – ConstraintLayout

Creating dialog in Jetpack compose

To create a custom dialog we need to use Dialog() composable.

@Composable
    fun Dialog(
        onDismissRequest: () -> Unit,
        properties: DialogProperties = DialogProperties(),
        content: @Composable () -> Unit
    )

The Dialog composable will accept three parameters.

onDismissRequest() – will be called when the dialog is dismissed. For example when we are clicking outside of the dialog.

DialogProperties

properties: DialogProperties

@Immutable
    class DialogProperties @ExperimentalComposeUiApi constructor(
        val dismissOnBackPress: Boolean = true,
        val dismissOnClickOutside: Boolean = true,
        val securePolicy: SecureFlagPolicy = SecureFlagPolicy.Inherit,
        @Suppress("EXPERIMENTAL_ANNOTATION_ON_WRONG_TARGET")
        @get:ExperimentalComposeUiApi
        val usePlatformDefaultWidth: Boolean = true
    )

Dialog Properties are used to customize the behavior of a Dialog.

dismissOnBackPress: Boolean – whether the dialog can be dismissed by pressing the back button.

dismissOnClickOutside: Boolean – whether the dialog can be dismissed by clicking outside the dialog’s bounds.

securePolicy – Policy for setting WindowManager.LayoutParams.FLAG_SECURE on the dialog window.

usePlatformDefaultWidth – Whether the width of the dialog’s content should be limited to the platform default, which is smaller than the screen width.

Jetpack composes custom dialog example

below, I am going to show three different custom alert dialog examples,

Custom dialog with Image

To create a custom dialog like this.

  • First, create Dialog composable and set dismissRequest and dialog properties.
  • Inside the dialog create your own view.
  • finally, set up the dismiss dialog on the desired button.
@Composable
  fun CustomAlertDialog(onDismiss: () -> Unit, onExit: () -> Unit) {

        Dialog(onDismissRequest = { onDismiss() }, properties = DialogProperties(
            dismissOnBackPress = false,dismissOnClickOutside = false
        )) {
            Card(
                //shape = MaterialTheme.shapes.medium,
                shape = RoundedCornerShape(10.dp),
                // modifier = modifier.size(280.dp, 240.dp)
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(8.dp),
                elevation = 8.dp
            ) {
                Column(
                    Modifier
                        .fillMaxWidth()
                        .background(Color.White)
                ) {

                    Row(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(100.dp)
                            .background(Color.Red.copy(alpha = 0.8F)),
                        verticalAlignment = Alignment.CenterVertically,
                        horizontalArrangement = Arrangement.Center,

                        ) {

                        Image(
                            painter = painterResource(id = R.drawable.background_image),
                            contentDescription = "Exit app",
                            modifier = Modifier.fillMaxSize(),
                            contentScale = ContentScale.FillWidth
                        )
                    }

                    Text(
                        text = "Lorem Ipsum is simply dummy text",
                        modifier = Modifier.padding(8.dp), fontSize = 20.sp
                    )

                    Text(
                        text = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard",
                        modifier = Modifier.padding(8.dp)
                    )

                    Row(Modifier.padding(top = 10.dp)) {
                        OutlinedButton(
                            onClick = { onDismiss() },
                            Modifier
                                .fillMaxWidth()
                                .padding(8.dp)
                                .weight(1F)
                        ) {
                            Text(text = "Cancel")
                        }

                        Button(
                            onClick = { onExit() },
                            Modifier
                                .fillMaxWidth()
                                .padding(8.dp)
                                .weight(1F)
                        ) {
                            Text(text = "Exit")
                        }
                    }

                }
            }
        }
  }

Now we have created the Custom dialog, to show the dialog on button click, you need to create a mutableStateOf() variable to maintain the dialog show and dismiss state.

Also, create conditions like if the variable is true call the dialog, otherwise don’t call the dialog function.

@Composable
    fun Content() {
        val context = LocalContext.current
        var showCustomDialog by remember {
            mutableStateOf(false)
        }

        Column(
            Modifier.fillMaxSize(),
            Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Button(onClick = { showCustomDialog = !showCustomDialog }, Modifier.wrapContentSize()) {
                Text(text = "Show Alert Dialog")
            }

        }

        if (showCustomDialog) {
            CustomAlertDialog({
                showCustomDialog = !showCustomDialog
            }, {
                val activity = (context as? Activity)
                activity?.finish()
            })
        }

    }

when clicking on the dismiss button on the dialog, need to update a variable to false to hide the dialog.

The final output of the code is below,

dialog with image and buttons

Alert dialog with Input field

As mentioned above, we need to create the dialog with a Dialog() composable function. But for the input field, we need to create a mutableStateOf() variable to hold the values of the input field.

@Composable
    fun InputDialogView(onDismiss:() -> Unit) {
        val context = LocalContext.current
        var searchedFood by remember {
            mutableStateOf("")
        }

        Dialog(onDismissRequest = { onDismiss() }) {
            Card(
                //shape = MaterialTheme.shapes.medium,
                shape = RoundedCornerShape(10.dp),
                // modifier = modifier.size(280.dp, 240.dp)
                modifier = Modifier.padding(8.dp),
                elevation = 8.dp
            ) {
                Column(
                    Modifier
                        .background(Color.White)
                ) {

                    Text(
                        text = "Search your favorite food",
                        modifier = Modifier.padding(8.dp),
                        fontSize = 20.sp
                    )

                    OutlinedTextField(
                        value = searchedFood,
                        onValueChange = { searchedFood = it }, modifier = Modifier.padding(8.dp),
                        label = { Text("Favorite Food") }
                    )

                    Row {
                        OutlinedButton(
                            onClick = { onDismiss() },
                            Modifier
                                .fillMaxWidth()
                                .padding(8.dp)
                                .weight(1F)
                        ) {
                            Text(text = "Cancel")
                        }

                        Button(
                            onClick = {
                                Toast.makeText(context, searchedFood, Toast.LENGTH_SHORT).show()
                                onDismiss() },
                            Modifier
                                .fillMaxWidth()
                                .padding(8.dp)
                                .weight(1F)
                        ) {
                            Text(text = "Search")
                        }
                    }

                }
            }
        }
    }

To display the dialog you need to follow the same way above. by creating the mutableStateOf() variable and making it true or false.

The output of the above code is,

dialog with input box

Loading Dialog

For the loading dialog, we need to use CircularProgressIndicator() composable function for loading animation. Apart from that everything is the same as other custom dialogs.

@Composable
    fun LoadingView(onDismiss:() -> Unit) {
        Dialog(onDismissRequest = { onDismiss() }) {

            Card(
                shape = RoundedCornerShape(8.dp),
                modifier = Modifier,
                elevation = 8.dp
            ) {
                Column(
                    Modifier
                        .background(Color.White)
                        .padding(12.dp)
                ) {
                    Text(
                        text = "Loading.. Please wait..",
                        Modifier
                            .padding(8.dp), textAlign = TextAlign.Center
                    )

                    CircularProgressIndicator(
                        strokeWidth = 4.dp,
                        modifier = Modifier
                            .align(Alignment.CenterHorizontally)
                            .padding(8.dp)
                    )
                }
            }
        }
    }

The output of the about loading dialog code,

loading dialog

That’s it. Thanks for reading. you can download this example on GitHub.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *


Latest Posts