Skip to content

Instantly share code, notes, and snippets.

@mxalbert1996
Last active October 12, 2021 06:59
Show Gist options
  • Save mxalbert1996/5c40b791846a4e68d1c9b10ce4a8654c to your computer and use it in GitHub Desktop.
Save mxalbert1996/5c40b791846a4e68d1c9b10ce4a8654c to your computer and use it in GitHub Desktop.
General-purpose AlertDialog for Jetpack Compose
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
@Composable
fun AlertDialog(
onDismissRequest: () -> Unit,
properties: DialogProperties = DialogProperties(),
title: @Composable (() -> Unit)? = null,
positiveButton: @Composable (() -> Unit)? = null,
negativeButton: @Composable (() -> Unit)? = null,
neutralButton: @Composable (() -> Unit)? = null,
content: @Composable () -> Unit
) {
Dialog(onDismissRequest = onDismissRequest, properties = properties) {
Box(
modifier = Modifier
.fillMaxSize()
.run {
if (properties.dismissOnClickOutside) {
pointerInput(onDismissRequest) {
detectTapGestures { onDismissRequest() }
}
} else this
},
contentAlignment = Alignment.Center
) {
AlertDialogLayout(title, positiveButton, negativeButton, neutralButton, content)
}
}
}
@Composable
private fun AlertDialogLayout(
title: @Composable (() -> Unit)? = null,
positiveButton: @Composable (() -> Unit)? = null,
negativeButton: @Composable (() -> Unit)? = null,
neutralButton: @Composable (() -> Unit)? = null,
content: @Composable () -> Unit
) {
Surface(
modifier = Modifier.pointerInput(Unit) { detectTapGestures {} },
shape = MaterialTheme.shapes.medium,
elevation = 24.dp
) {
Column(modifier = Modifier.animateContentSize()) {
if (title != null) {
Box(
modifier = Modifier.padding(
start = 24.dp,
top = 18.dp,
end = 24.dp,
bottom = 8.dp
)
) {
ProvideTextStyle(value = MaterialTheme.typography.h6) {
CompositionLocalProvider(
LocalContentAlpha provides ContentAlpha.high,
content = title
)
}
}
}
Box(modifier = Modifier.heightIn(min = 48.dp)) {
CompositionLocalProvider(
LocalContentAlpha provides ContentAlpha.medium,
content = content
)
}
if (positiveButton != null || negativeButton != null || neutralButton != null) {
@OptIn(ExperimentalMaterialApi::class)
CompositionLocalProvider(LocalMinimumTouchTargetEnforcement provides false) {
Row(
modifier = Modifier.padding(8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
neutralButton?.invoke()
Spacer(modifier = Modifier.weight(1f))
negativeButton?.invoke()
positiveButton?.invoke()
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment