날짜를 선택할 수 있게 해주는 컴포넌트 입니다.
html에서
<input type="date" />
type
속성이 date
인 태그는
이와 같이 날짜를 선택할 수 있게 해줍니다.
안드로이드에서는 위와 같이 달력에서 날짜를 선택하게 해주는 calendar
형식과 목록에서 직접 날짜를 선택할 수 있게 해주는 spinner
형식을 제공합니다.
calendar
타입의 DatePickercalendar
타입의 DatePicker는 아래와 같이 달력형식에서 날짜를 선택할 수 있게 해줍니다.
코드를 보면
<DatePicker
android:id="@+id/datePicker"
android:layout_width="320dp"
android:layout_height="430dp"
android:calendarViewShown="false"
android:datePickerMode="calendar"
app:layout_constraintTop_toBottomOf="@+id/button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
/>
datePickerMode
가 calendar
로 설정되어있음을 알 수 있습니다!
spinner
타입의 DatePickerDatePicker를 스피너 타입으로 주었을 때는 스피너를 통해 사용자가 직접 날짜를 입력할 수 있게 해줍니다.
이렇게 스피너로부터 날짜를 입력받을 수 있습니다.
이 때는
<DatePicker
android:id="@+id/datePicker"
android:layout_width="320dp"
android:layout_height="430dp"
android:calendarViewShown="false"
android:datePickerMode="spinner"
app:layout_constraintTop_toBottomOf="@+id/button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
/>
이와 같이 android:datePickerMode
를 spinner
로 주면 됩니다.
DatePicker의 타입이 캘린더 타입이든 스피너 타입이든 값을 얻어오는 방법은 동일합니다.
Calendar
라는 객체를 생성하고 거기에서 getInstance
라는 메서드를 통해 값을 얻어옵니다.
다음과 같이 뷰가 구성되어 있다고 할 때
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="388dp"
android:layout_height="94dp"
android:text="날짜 읽어오기"
android:textSize="25sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.116"
/>
<Button
android:id="@+id/button"
android:text="Button"
android:layout_width="188dp"
android:layout_height="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintVertical_bias="0.105"
app:layout_constraintTop_toBottomOf="@+id/textView"/>
<DatePicker
android:id="@+id/datePicker"
android:layout_width="320dp"
android:layout_height="430dp"
android:calendarViewShown="false"
android:datePickerMode="spinner"
app:layout_constraintTop_toBottomOf="@+id/button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
값을 얻어오고 버튼을 통해 텍스트뷰에 값을 넘겨줘보겠습니다.
import android.annotation.SuppressLint
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.DatePicker
import android.widget.TextView
import java.util.*
class MainActivity : AppCompatActivity(), View.OnClickListener {
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val calendar = Calendar.getInstance()
val year = calendar.get(Calendar.YEAR)
val month = calendar.get(Calendar.MONTH)
val dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH)
우선 초기값으로 오늘 날짜를 보여주기 위해 Calendar
객체의 getInstance
메서드를 통해서 값을 얻어옵니다.
이 때, 연월일은 각각 Calendar.YEAR
, Calendar.MONTH
, Calendar.DAY_OF_MONTH
라고 하는 값을 전달해서 get
으로 얻어옵니다.
val textView = findViewById<TextView>(R.id.textView)
val button = findViewById<Button>(R.id.button)
textView.text =
"""
초기 설정된 날짜 [년도/월/일]
$year/${month+1}/$dayOfMonth
""".trimIndent()
button.setOnClickListener(this)
}
텍스트뷰와 버튼을 아이디로 가져온 후 텍스트뷰의 초기값을 오늘 날짜로 지정해줍니다.
메인 클래스에서 View.OnClickListener
의 상속을 받았으므로 setOnClickListener
로 버튼 클릭시 발생하는 이벤트를 지정해줍니다.
@SuppressLint("SetTextI18n")
override fun onClick(view: View?) {
val textView = findViewById<TextView>(R.id.textView)
val datePicker = findViewById<DatePicker>(R.id.datePicker)
if(view?.id == R.id.button) {
textView.text = "초기 설정된 날짜 [년도/월/일] : \n" + datePicker.year.toString() + "/" +
(datePicker.month + 1).toString() + "/" + datePicker.dayOfMonth.toString()
}
}
}
onClick
함수를 오버라이드 해주었습니다.
파라미터로 받아온 뷰(버튼)이 클릭되었을 때 텍스트뷰를 사용자가 지정한 날짜로 바꿔줍니다.
시간을 선택할 수 있게 해주는 컴포넌트입니다.
마찬가지로 html에서는
<input type="time" />
<input>
의 타입을 time
으로 주면 시간을 입력받을 수 있습니다.
안드로이드에서는 DatePicker와 마찬가지로 스피너를 제공하며 시계UI에서 시간을 입력받기 위해서는 모드를 clock
으로 주면 됩니다.
clock
타입의 TimePicker시계 모양의 UI를 통해 시간값을 입력하게 할 수 있습니다.
코드를 보면
<TimePicker
android:id="@+id/timePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:timePickerMode="clock"
app:layout_constraintTop_toBottomOf="@+id/textView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintVertical_bias="0.275"
/>
timePickerMode
가 clock
으로 설정되어 있습니다.
spinner
타입의 TimePickerDatePicker와 마찬가지로 목록에서 직접 시간을 선택할 수 있게 해주는 spinner
타입도 제공합니다.
코드에서 timePickerMode
를 spinner
로 바꿔주면
<TimePicker
android:id="@+id/timePicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:timePickerMode="spinner"
app:layout_constraintTop_toBottomOf="@+id/textView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintVertical_bias="0.275"
/>
이렇게 스피너에서 값을 입력받을 수 있습니다.
DatePicker에서 값을 얻어오는 방법과 유사합니다.
주의사항은 이벤트 리스너를 사용할 때 TimePicker 값의 변화를 실시간으로 조회하길 원한다면 TimePicker.OnTimeChangedListener
를 상속받아야 한다는 것입니다.
여기서는 버튼클릭에 대한 이벤트가 아닌 값이 바뀔 때마다 조회해서 텍스트뷰에 뿌려주는 연습을 해보겠습니다.
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import android.widget.TimePicker
import java.util.*
class MainActivity : AppCompatActivity(), TimePicker.OnTimeChangedListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var cal = Calendar.getInstance()
val hour = cal.get(Calendar.HOUR_OF_DAY)
val minute = cal.get(Calendar.MINUTE)
텍스트뷰의 초기값(현재시간) 설정을 위해 현재시간을 가져와 보겠습니다.
Calendar
객체의 getInstance
메서드를 받아옵니다.
각각 시, 분을 get
메서드로 얻어오는데 매개변수로 각각 Calendar.HOUR_OF_DAY
, Calendar.MINUTE
을 사용했습니다.
val textView = findViewById<TextView>(R.id.textView)
val timePicker = findViewById<TimePicker>(R.id.timePicker)
textView.text = "현재 설정된 시간 : \n 시:분 | $hour : $minute"
timePicker.setOnTimeChangedListener(this)
}
텍스트뷰와 타임피커를 아이디로 가져오고 초기값을 우선 현재 시간으로 지정해줍니다.
그다음 타임피커의 값이 바뀔 때마다 그 값을 조회해서 텍스트뷰에 뿌려주기 위해 타임피커에 이벤트 리스너를 지정해줍니다.
override fun onTimeChanged(view: TimePicker?, hourOfDay: Int, minute: Int) {
val textView = findViewById<TextView>(R.id.textView)
textView.text = "현재 설정된 시간 : \n 시:분 | $hourOfDay : $minute"
}
}
타임피커의 값이 바뀔 때마다 텍스트뷰에 값을 뿌려줄 함수를 오버라이드하여 구현합니다.
TimePicker
에서는 원래 "초"단위를 입력받을 수 없습니다. UI에서 보면 아시겠지만 초를 입력하는 곳은 없습니다.
그래서 초를 얻어오기 위해서는 별도의 변수를 선언해서 초를 얻어와야 합니다.
오버라이드한 함수에 단위까지 출력하게 해주기 위해서는 val second:Int = Calendar.SECOND
를 별도로 선언해서 텍스트뷰에 집어넣어주면 됩니다.