안드로이드에서 사용자가 날짜를 선택할 수 있도록 DatePicke나 DatePickerDialog를 사용한다.

달력은 직접 만들려면 손이 많이 가서 잠깐 보여주는 용도면 거의 다 기본 뷰를 쓰는거 같다.

기본 뷰는 이렇게 생겼다

이미 지나간 날짜는 선택할 수 없다던가, 오늘 기준으로 1개월 이내의 날짜만 선택가능하게 한다던가... 사용자가 선택할 수 있는 날짜에 범위가 필요한 경우가 있다. '확인'버튼을 눌렀을 때 현재 선택된 날짜를 검사해서 선택이 불가능하다고 안내 메세지를 보여주는 방식으로도 처리할 수 있지만, DatePicker 자체에서 아예 선택을 막을 수 있게 minDate, maxDate 속성을 제공한다. xml에서 설정할수도 있고, 코드로 설정할 수도 있다.

 

설정하는 방법

date 값은 long 타입(milliseconds since January 1, 1970 00:00:00)으로만 설정이 가능하다.

 

방법 1. System.currentTimeMillis()

datePicker.minDate = System.currentTimeMillis()

System.currentTimeMillis를 사용하면 1/1000초 단위로 현재 시간이 long type으로 반환된다. 이 시간을 기준으로 원하는 날짜를 계산할 수 있다. 오늘 날짜 기준으로 N일 만큼 이동시키고 싶으면 하루 분량인 (24 * 60 * 60 * 1000) * N 을 계산해서 현재 시간에 더하기 또는 빼기 해주면 된다.

 

방법 2. Calendar 객체 사용하기

Calendar 객체의 add, set 함수를 사용하면 좀 더 직관적으로 원하는 날짜를 고를 수 있다.

val calendar: Calendar = Calendar.getInstance()
val currentTime = calendar.timeInMillis // 현재 시간

calendar.add(Calendar.DATE, -1)
val yesterday = calendar.timeInMillis // 내일

calendar.add(Calendar.YEAR, 1)
val nextYear = calendar.timeInMillis // 오늘로부터 1년 후 내년

// 이런 식으로 직접 날짜 설정도 가능
calendar.set(Calendar.YEAR, 2020)
calendar.set(2020, 6, 1)

적용된 모습

  • 왼쪽 - minDate를 오늘로 설정했을 때
  • 오른쪽 - maxDate를 오늘로 설정했을 때
  • 범위에서 벗어나는 날짜가 선택 불가능하게 비활성화 처리 된 것을 볼 수 있다.

DatePickerDialog 생성 예제

  1. 오늘 날짜를 기본값으로 설정하고
  2. 확인 버튼을 누르면 선택된 날짜를 받아오고
  3. 지나간 날짜는 선택할 수 없게 한다.
fun showDatePickerDialog() {
    val calendar: Calendar = Calendar.getInstance()
    DatePickerDialog(
        context,
        R.style.DialogStyle,
        OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
            // 선택된 날짜가 필요하면 이 currentDate 변수를 적절하게 사용하면 된다.
            val currentDate = Calendar.getInstance().apply { set(year, monthOfYear, dayOfMonth) }
            // ...
        },
        calendar.get(Calendar.YEAR),
        calendar.get(Calendar.MONTH),
        calendar.get(Calendar.DAY_OF_MONTH)
    ).apply {
        datePicker.minDate = System.currentTimeMillis()
    }.show()
}