Jetpack Compose에서 DatePickerDialog를 구현하는 방법에 대해 정리해보려 한다.
Material3에서 제공하는 DatePickerDialog와 DatePicker를 사용하여 DatePicker Dialog를 구현하였다.
DatePickerDialog
는 다이얼로그 형태로 날짜 선택을 표시하는 컴포저블이며DatePicker
컴포넌트를 포함하여 다이얼로그 안에 날짜 인터페이스를 제공한다.
- onDismissRequest : 다이얼로그 외부를 클릭하거나 취소 버튼을 클릭하여 다이얼로그를 닫을 때 호출되는 콜백 함수
- confirmButton : 다이얼로그에 표시될 확인 버튼
- colors : 다이얼로그의 색상을 정의
- shape : 다이얼로그의 모양을 정의
- properties : 다이얼로그의 추가 속성을 정의
DatePicker
는 날짜 선택 인터페이스를 제공하는 컴포저블로 날짜를 선택할 수 있는 UI 요소를 포함한다.
- state :
DatePicker
의 상태를 관리하는 객체로rememberDatePickerState
를 사용하여 초기 선택 날짜 등을 설정할 수 있다.- colors :
DatePicker
의 색상을 정의
@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun CustomDatePickerDialog(
date: LocalDate? = LocalDate.now(), // 선택된 날짜 설정
onClickCancel: () -> Unit,
onClickConfirm: (yyyyMMdd: String) -> Unit
) {
// 초기 선택 날짜를 밀리초로 변환하여 가져온다.
val initialDateMillis = date?.atStartOfDay(ZoneOffset.UTC)?.toInstant()?.toEpochMilli()
?: System.currentTimeMillis()
// DatePicker 상태를 기억하며 설정한다.
val datePickerState = rememberDatePickerState(
yearRange = IntRange(2000, 2050), // 연도 범위 설정
initialDisplayMode = DisplayMode.Picker, // 초기 표시 모드 설정
initialSelectedDateMillis = initialDateMillis, // 초기 선택된 날짜의 밀리초 값 설정
selectableDates = object : SelectableDates { // 선택 가능한 날짜를 정의하는 인터페이스 구현
override fun isSelectableDate(utcTimeMillis: Long): Boolean {
return true // 모든 날짜를 선택 가능하게 설정
}
}
)
// 초기 선택된 날짜를 기억한다.
val initialSelectedDate = remember { datePickerState.selectedDateMillis }
// 선택된 날짜가 변경될 때 실행되는 LaunchedEffect
LaunchedEffect(datePickerState.selectedDateMillis) {
if (initialSelectedDate != datePickerState.selectedDateMillis) {
datePickerState.selectedDateMillis?.let { selectedDateMillis ->
// 선택된 날짜를 yyyyMMdd 형식의 문자열로 변환한다.
val formatter = SimpleDateFormat(DATE_FORMAT_PATTERN, Locale.getDefault())
val formattedDate = formatter.format(Date(selectedDateMillis))
// 클릭 확인 이벤트를 호출하여 선택된 날짜를 전달한다.
onClickConfirm(formattedDate)
}
}
}
// DatePickerDialog 구성
DatePickerDialog(
onDismissRequest = { onClickCancel() }, // 취소 버튼 클릭 시 호출할 함수
confirmButton = {}, // 날짜를 선택하면 Dialog를 dismiss하기에 확인 버튼을 정의하지 않음
colors = DatePickerDefaults.colors(
containerColor = MaterialTheme.colors.white // DatePicker의 배경색 설정
),
shape = Shapes.small, // 다이얼로그의 모양에 radius 적용
properties = DialogProperties(usePlatformDefaultWidth = false) // 기본 너비 사용 안 함
) {
// DatePicker 설정
DatePicker(
state = datePickerState, // DatePicker 상태를 전달
colors = DatePickerDefaults.colors(
selectedDayContainerColor = MaterialTheme.colors.primary, // 선택된 날짜의 날짜 부분 배경색 설정
selectedYearContainerColor = MaterialTheme.colors.primary, // 선택된 날짜의 연도 부분 배경색 설정
containerColor = MaterialTheme.colors.white, // DatePicker의 전체 배경색 설정
todayDateBorderColor = MaterialTheme.colors.primary, // 오늘 날짜의 테두리 색상 설정
todayContentColor = MaterialTheme.colors.black, // 오늘 날짜의 텍스트 색상 설정
selectedDayContentColor = MaterialTheme.colors.black, // 선택된 날짜의 텍스트 색상 설정
dateTextFieldColors = TextFieldDefaults.colors(
unfocusedContainerColor = Color.Transparent, // 포커스가 없는 상태의 배경색을 투명으로 설정
focusedContainerColor = Color.Transparent, // 포커스가 있는 상태의 배경색을 투명으로 설정
focusedIndicatorColor = MaterialTheme.colors.primary, // 포커스가 있는 상태의 인디케이터 색상을 설정
unfocusedIndicatorColor = MaterialTheme.colors.primary, // 포커스가 없는 상태의 인디케이터 색상을 설정
disabledIndicatorColor = MaterialTheme.colors.primary, // 비활성화 상태의 인디케이터 색상을 설정
cursorColor = MaterialTheme.colors.primary, // 커서의 색상을 설정
focusedTextColor = MaterialTheme.colors.primary, // 포커스가 있는 상태의 텍스트 색상을 설정
errorContainerColor = Color.Transparent, // 오류 메시지가 나타날 때의 배경 색상을 투명으로 설정
focusedLabelColor = MaterialTheme.colors.primary, // 포커스가 있는 상태의 라벨 텍스트 색상을 설정
unfocusedLabelColor = MaterialTheme.colors.primary, // 포커스가 없는 상태의 라벨 텍스트 색상을 설정
disabledLabelColor = MaterialTheme.colors.primary, // 비활성화 상태의 라벨 텍스트 색상을 설정
),
)
)
}
}
☝🏻 위의 내용을 다시 한 번 정리하면
1. DatePickerDialog는 다이얼로그 형태로 DatePicker를 표시한다.
2. DatePicker는 날짜를 선택할 수 있는 UI를 제공한다.
3. 선택된 날짜를 LaunchedEffect를 통해 감지하고 날짜 선택시 onClickConfirm 콜백 함수를 호출하여 선택된 날짜를 반환한다.