목차

목적

안드로이드 Jetpack compose로 날짜 선택도구(Date Picker)를 구현해 보자

기본 컴퍼넌트

1. Date Picker

안드로이드에서는 DatePicker에서 선택 한 일자를 Long형태로, DatePickerState로 반환해 준다.

따라서 rememberDatePickerState()로 지정된 변수를 반환해 주면 날짜를 Long 형태롤 얻을 수 있다.

참고로, DatePicker는 Dialog 형태의 팝업으로 나와야 할 것이다. 이를 코드로 하면 다음과 같다.

// 캘린더
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DatePickerModal(
    onDateSelected: (Long?) -> Unit,
    onDismiss: () -> Unit
) {
    val datePickerState = rememberDatePickerState()
 
    DatePickerDialog(
        onDismissRequest = onDismiss,
        confirmButton = {
            TextButton(onClick = {
                onDateSelected(datePickerState.selectedDateMillis)
                onDismiss()
 
            }) {
                Text(stringResource(id = R.string.confirm))
            }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) {
                Text(stringResource(id = R.string.dismiss))
            }
        }
    ) {
        DatePicker(state = datePickerState,
            title = {
                Text(text = "   날짜 선택")
            },
            headline = {
                Text(text = " 직접 날자를 입력하려며 펜 버튼 클릭")
            },
            )
    }
}

2. Long값을 String으로 변환하는 컨버터

날짜를 Long값으로 가져오므로, 이를 사람이 읽을 수 있게 String으로 반환해야 한다.

SimpleDateFormat이란 함수를 이용하면 날자의 Format을 정할 수 있다.

// 날자의 Long값을 String으로 변환하는 함수 
fun convertMillisToDate(millis: Long?): String {
 
    var message : String = ""
    if (millis != null) {
        val date = Date(millis)
        message = SimpleDateFormat("yyyy-MM-dd", Locale.KOREAN).format(date)
    }else {
        message = "날짜가 선택되지 않았습니다."
    }
 
    return message
}

선택한 날짜를 텍스트필드와 연결하기

날짜선택도구를 만들었으면, 이를 텍스트 필드와 연결해야 할 것이다. 라벨로 보여줄 수도 있지만 관례적으로 텍스트 필드를 통해 날짜를 보여주므로 우리도 텍스트 필드로 날자를 보여주게 만들어보자.

//  날짜 입력 컴퍼저블
@Composable
fun dateAddWithCalendar(storedDate : Long?) : Long
{
    var showDatePicker by remember { mutableStateOf(false) }
 
    var selectedDate by remember { mutableStateOf<Long?>(storedDate) }
 
 
    OutlinedTextField(
        value =  convertMillisToDate(selectedDate),
        onValueChange = { },
        label = { Text(text = stringResource(id = R.string.selectDate), color = Color.Blue, fontSize = 14.sp, style = TextStyle(fontFamily = fontGoryeong))  },
        readOnly = true,
        trailingIcon = {
            IconButton(onClick = { showDatePicker = !showDatePicker }) {
                Icon(
                    imageVector = Icons.Default.DateRange,
                    contentDescription = "Select date"
                )
            }
        },
        textStyle = TextStyle(fontFamily = fontkjcMyungjo, fontSize = 16.sp, fontWeight = FontWeight.SemiBold, fontStyle = FontStyle.Normal),
        keyboardOptions = KeyboardOptions.Default,
        modifier = Modifier
            .fillMaxWidth()
            .height(64.dp)
    )
 
    if (showDatePicker)
    {
        DatePickerModal(onDateSelected = { selectedDate = it}, onDismiss = {showDatePicker = false })
    }
 
 
    return selectedDate?:12133
}

실제 코드에서 구현하기

다음은 Json으로 받아온 날자를 다시 Long값으로 변환한 후에 이를 날자 선택 텍스트 필드에 변수로 넣어주고,

날찌입력 선택도구에서 날자를 선택하면 텍스트 필드의 값이 다시 바뀌는 것을 구현한 것이다.

                val jsonAttackedDate = jsonElementObject.optString("attackedDate", Date.from(Instant.now()).time.toString())
 
                val attackedDate by remember { mutableStateOf(jsonAttackedDate.toLongOrNull())}
                var setAttackedDate : Long? = 1
 
                Spacer(modifier = Modifier.height(40.dp))
 
                ElevatedCard(elevation = CardDefaults.cardElevation(defaultElevation = 6.dp), modifier = Modifier
                    .fillMaxWidth()
                    .padding(6.dp)) {
                    Column(
                        modifier = Modifier
                            .fillMaxWidth()
                            .padding(8.dp), horizontalAlignment = Alignment.Start
                    ) {
                        setAttackedDate = dateAddWithCalendar(attackedDate)
                    }
                }