[Kotlin / Compose] Material3 DatePickerDialog

Subeen·2024년 6월 24일
0

Compose

목록 보기
15/20

Jetpack Compose에서 DatePickerDialog를 구현하는 방법에 대해 정리해보려 한다.
Material3에서 제공하는 DatePickerDialog와 DatePicker를 사용하여 DatePicker Dialog를 구현하였다.

DatePickerDialog

DatePickerDialog는 다이얼로그 형태로 날짜 선택을 표시하는 컴포저블이며 DatePicker 컴포넌트를 포함하여 다이얼로그 안에 날짜 인터페이스를 제공한다.

  • onDismissRequest : 다이얼로그 외부를 클릭하거나 취소 버튼을 클릭하여 다이얼로그를 닫을 때 호출되는 콜백 함수
  • confirmButton : 다이얼로그에 표시될 확인 버튼
  • colors : 다이얼로그의 색상을 정의
  • shape : 다이얼로그의 모양을 정의
  • properties : 다이얼로그의 추가 속성을 정의

DatePicker

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 콜백 함수를 호출하여 선택된 날짜를 반환한다.

profile
개발 공부 기록 🌱

0개의 댓글