an.png

Objective

Implement Material Design 3 DatePickerDialog() & DatePicker() in an Android Compose app, to display the selected date as a formatted string.

Environment

Implementation

// Your package

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.DatePicker
import androidx.compose.material3.DatePickerDefaults
import androidx.compose.material3.DatePickerDialog
import androidx.compose.material3.DisplayMode
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.rememberDatePickerState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale

@OptIn(ExperimentalMaterial3Api::class)
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            // Initial state setup for the DatePickerDialog. Specifies to show the picker initially
            val datePickerState = rememberDatePickerState(initialDisplayMode = DisplayMode.Picker)
            // State to hold the selected date as a String
            val selectedDateLabel = remember { mutableStateOf("") }
            // State to control the visibility of the DatePickerDialog
            val openDialog = remember { mutableStateOf(false) }
            // Define the main color for the calendar picker
            val calendarPickerMainColor = Color(0xFF722276)

            // Layout for displaying the button and the selected date
            Column(
                modifier = Modifier.fillMaxSize(),
                horizontalAlignment = Alignment.CenterHorizontally,
                verticalArrangement = Arrangement.Center
            ) {
                // Button to open the DatePickerDialog
                Button(
                    onClick = {
                        openDialog.value = !openDialog.value
                    }
                ) {
                    Text("Open Date Picker")
                }
                // Displays the selected date
                Text("Selected Date: ${selectedDateLabel.value}")
            }

            // Conditional display of the DatePickerDialog based on the openDialog state
            if (openDialog.value) {
                // DatePickerDialog component with custom colors and button behaviors
                DatePickerDialog(
                    colors = DatePickerDefaults.colors(
                        containerColor = Color(0xFFF5F0FF),
                    ),
                    onDismissRequest = {
                        // Action when the dialog is dismissed without selecting a date
                        openDialog.value = false
                    },
                    confirmButton = {
                        // Confirm button with custom action and styling
                        TextButton(
                            onClick = {
                                // Action to set the selected date and close the dialog
                                openDialog.value = false
                                selectedDateLabel.value =
                                    datePickerState.selectedDateMillis?.convertMillisToDate() ?: ""
                            }
                        ) {
                            Text("OK", color = calendarPickerMainColor)
                        }
                    },
                    dismissButton = {
                        // Dismiss button to close the dialog without selecting a date
                        TextButton(
                            onClick = {
                                openDialog.value = false
                            }
                        ) {
                            Text("CANCEL", color = calendarPickerMainColor)
                        }
                    }
                ) {
                    // The actual DatePicker component within the dialog
                    DatePicker(
                        state = datePickerState,
                        colors = DatePickerDefaults.colors(
                            selectedDayContainerColor = calendarPickerMainColor,
                            selectedDayContentColor = Color.White,
                            selectedYearContainerColor = calendarPickerMainColor,
                            selectedYearContentColor = Color.White,
                            todayContentColor = calendarPickerMainColor,
                            todayDateBorderColor = calendarPickerMainColor
                        )
                    )
                }
            }
        }
    }
}

fun Long.convertMillisToDate(): String {
    // Create a calendar instance in the default time zone
    val calendar = Calendar.getInstance().apply {
        timeInMillis = this@convertMillisToDate
        // Adjust for the time zone offset to get the correct local date
        val zoneOffset = get(Calendar.ZONE_OFFSET)
        val dstOffset = get(Calendar.DST_OFFSET)
        add(Calendar.MILLISECOND, -(zoneOffset + dstOffset))
    }
    // Format the calendar time in the specified format
    val sdf = SimpleDateFormat("MMM dd, yyyy", Locale.US)
    return sdf.format(calendar.time)
}

Result

untitled.gif

More Resources

For developers eager to deepen their understanding or explore more about modern Android development, a wealth of resources and guides await.

Android Compose Tutorials Library

The Ultimate Android Development Career Guide

Your thoughts and involvement are truly priceless. If you've found this guide helpful, I'd love to hear from you. Consider sharing your support through claps or a follow, and stay tuned for more insights into the evolving landscape of Android development. See you in the next tutorial!