JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
15.33k stars 1.12k forks source link

Show an AlertDialog in Android & iOS #3271

Closed iadcialim closed 1 year ago

iadcialim commented 1 year ago

Isn't there an API for showing a simple AlertDialog in Android & iOS? I only see code for desktop platform.

Nailik commented 1 year ago

You can use the Popup composable for both Platforms but it's a different function with different parameters, so i build myself an expected DialogContainer that then actually implements the Popup composable. Depending on how you set it up you have to care about backPress by yourself.

iadcialim commented 1 year ago

@Nailik Can you share your code for that?

Nailik commented 1 year ago

Expected:

@Composable
expect fun DialogContainer(content: @Composable () -> Unit)

Actual Android:

@Composable
actual fun DialogContainer(content: @Composable () -> Unit) {

    Popup(content = content) //via popupProperties you can handle outside click and back press etc

}

Actual iOS:

@Composable
actual fun DialogContainer(content: @Composable () -> Unit) {

    Popup(content = content)

}

Usage in shared (rebuild the material3 spec dialog):

@Composable
private fun Dialog(
    modifier: Modifier = Modifier,
    onDismissRequest: () -> Unit,
    icon: (@Composable () -> Unit)? = null,
    headline: @Composable () -> Unit,
    supportingText: (@Composable () -> Unit)? = null,
    confirmButton: @Composable () -> Unit,
    dismissButton: (@Composable () -> Unit)? = null,
    dismissOnOutside: Boolean = true,
    showDivider: Boolean = false
) {
    DialogContainer {

        //Scrim
        Surface(
            modifier = modifier
                .fillMaxSize()
                .clickable(enabled = dismissOnOutside, onClick = onDismissRequest),
            color = MaterialTheme.colorScheme.scrim.copy(alpha = 0.5f)
        ) {

            //Container
            Surface(
                modifier = Modifier
                    .widthIn(min = 280.dp, max = 560.dp)
                    .padding(48.dp)
                    .wrapContentHeight()
                    .clip(RoundedCornerShape(28.dp))
                    .clickable(enabled = false) { },
                shape = RoundedCornerShape(28.dp),
                color = MaterialTheme.colorScheme.surface,
                tonalElevation = 6.dp
            ) {
                Column(
                    modifier = Modifier.padding(24.dp),
                    horizontalAlignment = Alignment.Start
                ) {

                    Column(
                        modifier = Modifier
                            .weight(weight = 1f, fill = false)
                    ) {
                        if (icon != null) {
                            Box(
                                modifier = Modifier
                                    .padding(bottom = 16.dp)
                                    .fillMaxWidth(),
                                contentAlignment = Alignment.Center,
                            ) {
                                Box(
                                    modifier = Modifier.size(24.dp),
                                ) {
                                    CompositionLocalProvider(
                                        LocalContentColor provides MaterialTheme.colorScheme.secondary,
                                    ) {
                                        //Icon (optional)
                                        icon()
                                    }
                                }
                            }
                        }

                        CompositionLocalProvider(
                            LocalContentColor provides MaterialTheme.colorScheme.onSurface,
                            LocalTextStyle provides MaterialTheme.typography.headlineSmall
                        ) {
                            //Headline
                            headline()
                            Spacer(modifier = Modifier.height(16.dp))
                        }

                        if (supportingText != null) {
                            CompositionLocalProvider(
                                LocalContentColor provides MaterialTheme.colorScheme.onSurfaceVariant,
                                LocalTextStyle provides MaterialTheme.typography.bodyMedium.copy(textAlign = TextAlign.Start)
                            ) {
                                //Supporting text
                                supportingText()
                            }
                        }

                        //Divider (optional)
                        if (showDivider) {
                            Divider()
                        }
                    }

                    CompositionLocalProvider(
                        LocalContentColor provides MaterialTheme.colorScheme.primary,
                        LocalTextStyle provides MaterialTheme.typography.labelLarge.copy(textAlign = TextAlign.Start)
                    ) {
                        //Text button
                        Row(
                            modifier = Modifier.padding(top = 24.dp),
                            horizontalArrangement = Arrangement.spacedBy(8.dp),
                            verticalAlignment = Alignment.CenterVertically
                        ) {
                            Spacer(modifier = Modifier.weight(1f))

                            //Dismiss
                            dismissButton?.invoke()

                            //Confirm
                            confirmButton()
                        }
                    }

                }

            }
        }

    }

}
MatkovIvan commented 1 year ago

Making AlertDialog available from common sourceset is in our plan. No exact ETA yet, most likely Q4

Closing as duplicate of #762

iadcialim commented 1 year ago

@Nailik Thanks for your code! It works

realityexpander commented 9 months ago

@Nailik thanks for the code, it works great. This should be standard library functionality.

Nailik commented 9 months ago

At least AlterDialog itself is available since 1.5 see https://github.com/JetBrains/compose-multiplatform/issues/762#issuecomment-1733035632 Also in my Code there might be issues with the buttons if the device is not big enough for the text ;)