날짜 선택 도구를 사용하면 사용자가 날짜, 기간 또는 둘 다를 선택할 수 있습니다. 캘린더 대화상자 또는 텍스트 입력을 사용하여 사용자가 날짜를 선택할 수 있도록 합니다.
유형
날짜 선택기에는 세 가지 유형이 있습니다.
- 도킹됨: 레이아웃 내에 인라인으로 표시됩니다. 전용 대화상자가 방해가 될 수 있는 좁은 레이아웃에 적합합니다.
- 모달: 앱 콘텐츠를 오버레이하는 대화상자로 표시됩니다. 이렇게 하면 날짜 선택에 명확하게 집중할 수 있습니다.
- 모달 입력: 텍스트 필드를 모달 날짜 선택 도구와 결합합니다.
다음 컴포저블을 사용하여 앱에서 이러한 날짜 선택 도구를 구현할 수 있습니다.
DatePicker
: 날짜 선택 도구의 일반 컴포저블입니다. 사용하는 컨테이너에 따라 도킹 또는 모델인지 결정됩니다.DatePickerDialog
: 모달 및 모달 입력 날짜 선택 도구의 컨테이너입니다.DateRangePicker
: 사용자가 시작일과 종료일이 있는 기간을 선택할 수 있는 모든 날짜 선택 도구에 적용됩니다.
상태
다양한 날짜 선택 도구 컴포저블에서 공통적으로 사용하는 키 매개변수는 state
이며, 이 매개변수는 DatePickerState
또는 DateRangePickerState
객체를 사용합니다. 이러한 속성은 현재 선택한 날짜와 같이 날짜 선택 도구를 사용하여 사용자의 선택에 관한 정보를 캡처합니다.
선택한 날짜를 사용하는 방법에 관한 자세한 내용은 선택한 날짜 사용 섹션을 참고하세요.
고정된 날짜 선택 도구
다음 예에는 사용자에게 생년월일을 입력하라는 메시지가 표시되는 텍스트 필드가 있습니다. 입력란에서 캘린더 아이콘을 클릭하면 입력란 아래에 고정된 날짜 선택기가 열립니다.
@Composable fun DatePickerDocked() { var showDatePicker by remember { mutableStateOf(false) } val datePickerState = rememberDatePickerState() val selectedDate = datePickerState.selectedDateMillis?.let { convertMillisToDate(it) } ?: "" Box( modifier = Modifier.fillMaxWidth() ) { OutlinedTextField( value = selectedDate, onValueChange = { }, label = { Text("DOB") }, readOnly = true, trailingIcon = { IconButton(onClick = { showDatePicker = !showDatePicker }) { Icon( imageVector = Icons.Default.DateRange, contentDescription = "Select date" ) } }, modifier = Modifier .fillMaxWidth() .height(64.dp) ) if (showDatePicker) { Popup( onDismissRequest = { showDatePicker = false }, alignment = Alignment.TopStart ) { Box( modifier = Modifier .fillMaxWidth() .offset(y = 64.dp) .shadow(elevation = 4.dp) .background(MaterialTheme.colorScheme.surface) .padding(16.dp) ) { DatePicker( state = datePickerState, showModeToggle = false ) } } } } } @Composable fun DatePickerFieldToModal(modifier: Modifier = Modifier) { var selectedDate by remember { mutableStateOf<Long?>(null) } var showModal by remember { mutableStateOf(false) } OutlinedTextField( value = selectedDate?.let { convertMillisToDate(it) } ?: "", onValueChange = { }, label = { Text("DOB") }, placeholder = { Text("MM/DD/YYYY") }, trailingIcon = { Icon(Icons.Default.DateRange, contentDescription = "Select date") }, modifier = modifier .fillMaxWidth() .pointerInput(selectedDate) { awaitEachGesture { // Modifier.clickable doesn't work for text fields, so we use Modifier.pointerInput // in the Initial pass to observe events before the text field consumes them // in the Main pass. awaitFirstDown(pass = PointerEventPass.Initial) val upEvent = waitForUpOrCancellation(pass = PointerEventPass.Initial) if (upEvent != null) { showModal = true } } } ) if (showModal) { DatePickerModal( onDateSelected = { selectedDate = it }, onDismiss = { showModal = false } ) } } fun convertMillisToDate(millis: Long): String { val formatter = SimpleDateFormat("MM/dd/yyyy", Locale.getDefault()) return formatter.format(Date(millis)) }
코드 관련 핵심 사항
- 사용자가
IconButton
를 클릭하면 날짜 선택 도구가 표시됩니다.- 아이콘 버튼은
OutlinedTextField
의trailingIcon
매개변수의 인수 역할을 합니다. showDatePicker
상태 변수는 고정된 날짜 선택 도구의 가시성을 제어합니다.
- 아이콘 버튼은
- 날짜 선택 도구의 컨테이너는
Popup
컴포저블로, 다른 요소의 레이아웃에 영향을 주지 않고 콘텐츠를 오버레이합니다. selectedDate
는DatePickerState
객체에서 선택한 날짜의 값을 캡처하고convertMillisToDate
함수를 사용하여 형식을 지정합니다.- 선택한 날짜가 텍스트 필드에 표시됩니다.
- 고정된 날짜 선택 도구는
offset
수정자를 사용하여 텍스트 필드 아래에 배치됩니다. Box
는 텍스트 필드와 날짜 선택 도구를 적절하게 레이어링할 수 있도록 루트 컨테이너로 사용됩니다.
결과
캘린더 아이콘을 클릭하면 이 구현은 다음과 같이 표시됩니다.
모달 날짜 선택 도구
모달 날짜 선택 도구는 화면 위에 플로팅되는 대화상자를 표시합니다. 이를 구현하려면 DatePickerDialog
를 만들고 DatePicker
를 전달합니다.
@Composable fun DatePickerModal( onDateSelected: (Long?) -> Unit, onDismiss: () -> Unit ) { val datePickerState = rememberDatePickerState() DatePickerDialog( onDismissRequest = onDismiss, confirmButton = { TextButton(onClick = { onDateSelected(datePickerState.selectedDateMillis) onDismiss() }) { Text("OK") } }, dismissButton = { TextButton(onClick = onDismiss) { Text("Cancel") } } ) { DatePicker(state = datePickerState) } }
코드 관련 핵심 사항
- 구성 가능한
DatePickerModal
함수는 모달 날짜 선택 도구를 표시합니다. onDateSelected
람다 표현식은 사용자가 날짜를 선택할 때 실행됩니다.- 선택한 날짜를 상위 컴포저블에 노출합니다.
onDismiss
람다 표현식은 사용자가 대화상자를 닫을 때 실행됩니다.
결과
이 구현은 다음과 같이 표시됩니다.
입력 모달 날짜 선택 도구
입력이 있는 모달 날짜 선택 도구는 화면 위에 플로팅되어 사용자가 날짜를 입력할 수 있는 대화상자를 표시합니다.
@Composable fun DatePickerModalInput( onDateSelected: (Long?) -> Unit, onDismiss: () -> Unit ) { val datePickerState = rememberDatePickerState(initialDisplayMode = DisplayMode.Input) DatePickerDialog( onDismissRequest = onDismiss, confirmButton = { TextButton(onClick = { onDateSelected(datePickerState.selectedDateMillis) onDismiss() }) { Text("OK") } }, dismissButton = { TextButton(onClick = onDismiss) { Text("Cancel") } } ) { DatePicker(state = datePickerState) } }
코드 관련 핵심 사항
이는 모달 날짜 선택 도구 예시와 매우 유사합니다. 주요 차이점은 다음과 같습니다.
initialDisplayMode
매개변수는 초기 디스플레이 모드를DisplayMode.Input
로 설정합니다.
기간이 있는 날짜 선택기
사용자가 시작일과 종료일 사이의 기간을 선택할 수 있는 날짜 선택 도구를 만들 수 있습니다. 이렇게 하려면 DateRangePicker
를 사용합니다.
DateRangePicker
의 사용은 기본적으로 DatePicker
와 동일합니다. PopUp
의 하위 요소로 고정된 선택 도구에 사용할 수 있으며 모달 선택 도구로 사용하고 DatePickerDialog
에 전달할 수도 있습니다. 주요 차이점은 DatePickerState
대신 DateRangePickerState
를 사용한다는 점입니다.
다음 스니펫은 범위가 있는 모달 날짜 선택 도구를 만드는 방법을 보여줍니다.
@Composable fun DateRangePickerModal( onDateRangeSelected: (Pair<Long?, Long?>) -> Unit, onDismiss: () -> Unit ) { val dateRangePickerState = rememberDateRangePickerState() DatePickerDialog( onDismissRequest = onDismiss, confirmButton = { TextButton( onClick = { onDateRangeSelected( Pair( dateRangePickerState.selectedStartDateMillis, dateRangePickerState.selectedEndDateMillis ) ) onDismiss() } ) { Text("OK") } }, dismissButton = { TextButton(onClick = onDismiss) { Text("Cancel") } } ) { DateRangePicker( state = dateRangePickerState, title = { Text( text = "Select date range" ) }, showModeToggle = false, modifier = Modifier .fillMaxWidth() .height(500.dp) .padding(16.dp) ) } }
코드 관련 핵심 사항
onDateRangeSelected
매개변수는 선택한 시작일과 종료일을 나타내는Pair<Long?, Long?>
를 수신하는 콜백입니다. 이렇게 하면 상위 컴포저블이 선택한 범위에 액세스할 수 있습니다.rememberDateRangePickerState()
는 기간 선택 도구의 상태를 만듭니다.DatePickerDialog
는 모달 대화상자 컨테이너를 만듭니다.- 확인 버튼의
onClick
핸들러에서onDateRangeSelected
은 선택한 범위를 상위 컴포저블로 전달합니다. DateRangePicker
컴포저블은 대화상자 콘텐츠 역할을 합니다.
결과
이 구현은 다음과 같이 표시됩니다.
선택한 날짜 사용
선택한 날짜를 캡처하려면 상위 컴포저블에서 Long
로 추적하고 onDateSelected
의 DatePicker
에 값을 전달합니다. 다음 스니펫은 이를 보여줍니다. 전체 구현은 공식 스니펫 앱에서 확인할 수 있습니다.
// ... var selectedDate by remember { mutableStateOf<Long?>(null) } // ... if (selectedDate != null) { val date = Date(selectedDate!!) val formattedDate = SimpleDateFormat("MMM dd, yyyy", Locale.getDefault()).format(date) Text("Selected date: $formattedDate") } else { Text("No date selected") } // ... DatePickerModal( onDateSelected = { selectedDate = it showModal = false }, onDismiss = { showModal = false } ) } // ...
기간 날짜 선택 도구에도 기본적으로 동일하게 적용되지만 Pair<Long?, Long?>
또는 데이터 클래스를 사용하여 시작 값과 종료 값을 캡처해야 합니다.