
This is a Jetpack Compose custom dialog design. It shows a delete warning message. It is made with Dialog API. You can download the source code for free below.
When you launch the activity, it shows a button with the text “Open Dialog.” If you tap on it, the dialog will show up. The UI contains composables like Icon, Button, and Text. The dialog box background color is transparent so that the delete icon appears floating on the screen.
The Jetpack Compose custom dialog takes multiple parameters like button colors, context, and space between the composables. The button colors are for the positive and negative buttons. The positive button has a red color and the negative one has primary color. The context is used to display the Toast message. The spaceBetweenElements is for the gap between the Text composables. You can customize them according to your requirements.
When you tap on the yes or no buttons, it shows a Toast message. I’m using the state hosting to display the toast. The whole custom dialog is covered with Surface composable. It has Box child. Inside the Box, there is a Column and Icon. All of them are placed nicely to make the dialog look beautiful.
You need to download the latest version of Android Studio to use the code. Jetpack Compose doesn’t work in the older versions.
Related:
Final output:
If the video isn’t working, watch it on the YouTube.
Helpful links to understand the code:
Here are the Gradle files used in the project.
For the delete icon, download it from feature icons. Open the site and search for “trash 2”. You will get the svg icon. But, you need to convert the icon to XML format. Here is the tutorial on how to convert SVG icons to XML in Android Studio.
Here is the source code:
MainActivity.kt:
import android.content.Context
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
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.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
/*
You can use the following code for commercial purposes with some restrictions.
Read the full license here: https://semicolonspace.com/semicolonspace-license/
For more designs with source code, visit:
https://semicolonspace.com/jetpack-compose-samples/
*/
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
YourProjectNameTheme(darkTheme = false) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
DeleteDialogBox()
}
}
}
}
}
@Composable
fun DeleteDialogBox(
negativeButtonColor: Color = Color(0xFF35898F),
positiveButtonColor: Color = Color(0xFFFF0000),
spaceBetweenElements: Dp = 18.dp,
context: Context = LocalContext.current.applicationContext
) {
var dialogOpen by remember {
mutableStateOf(false)
}
if (dialogOpen) {
Dialog(onDismissRequest = {
dialogOpen = false
}
) {
Surface(
modifier = Modifier.fillMaxWidth(0.92f),
color = Color.Transparent // dialog background
) {
Box(
modifier = Modifier
.fillMaxWidth()
) {
// text and buttons
Column(
modifier = Modifier
.padding(top = 30.dp) // this is the empty space at the top
.fillMaxWidth()
.background(
color = Color.White,
shape = RoundedCornerShape(percent = 10)
),
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(modifier = Modifier.height(height = 36.dp))
Text(
text = "Delete?",
fontFamily = FontFamily(Font(R.font.roboto_medium, FontWeight.Bold)),
fontSize = 24.sp
)
Spacer(modifier = Modifier.height(height = spaceBetweenElements))
Text(
modifier = Modifier.padding(horizontal = 16.dp),
text = "Are you sure, you want to delete the item?",
fontFamily = FontFamily(Font(R.font.roboto_regular, FontWeight.Normal)),
fontSize = 18.sp
)
Spacer(modifier = Modifier.height(height = spaceBetweenElements))
// buttons
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceAround
) {
DialogButton(buttonColor = negativeButtonColor, buttonText = "No") {
Toast
.makeText(context, "No Click", Toast.LENGTH_SHORT)
.show()
dialogOpen = false
}
DialogButton(buttonColor = positiveButtonColor, buttonText = "Yes") {
Toast
.makeText(context, "Yes Click", Toast.LENGTH_SHORT)
.show()
dialogOpen = false
}
}
// If you decrease the Surface's width, increase this height
Spacer(modifier = Modifier.height(height = spaceBetweenElements * 2))
}
// delete icon
Icon(
painter = painterResource(id = R.drawable.trash_2),
contentDescription = "Delete Icon",
tint = positiveButtonColor,
modifier = Modifier
.background(color = Color.White, shape = CircleShape)
.border(width = 2.dp, shape = CircleShape, color = positiveButtonColor)
.padding(all = 16.dp)
.align(alignment = Alignment.TopCenter)
)
}
}
}
}
Button(onClick = { dialogOpen = true }) {
Text(text = "OPEN DIALOG")
}
}
@Composable
fun DialogButton(
cornerRadiusPercent: Int = 26,
buttonColor: Color,
buttonText: String,
onDismiss: () -> Unit
) {
Box(
modifier = Modifier
.background(
color = buttonColor,
shape = RoundedCornerShape(percent = cornerRadiusPercent)
)
.clickable {
onDismiss()
}
.padding(horizontal = 16.dp, vertical = 6.dp)
) {
Text(
text = buttonText,
color = Color.White,
fontSize = 18.sp,
fontFamily = FontFamily(Font(R.font.roboto_medium, FontWeight.Medium))
)
}
}