Android : DatePicker와 TimePicker

Beautify.log·2022년 2월 9일
0

Android with Kotlin

목록 보기
13/17
post-thumbnail

DatePicker


개요

날짜를 선택할 수 있게 해주는 컴포넌트 입니다.

html에서

<input type="date" />

type 속성이 date인 태그는

이와 같이 날짜를 선택할 수 있게 해줍니다.

안드로이드에서는 위와 같이 달력에서 날짜를 선택하게 해주는 calendar 형식과 목록에서 직접 날짜를 선택할 수 있게 해주는 spinner 형식을 제공합니다.

calendar 타입의 DatePicker

calendar 타입의 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"
/>

datePickerModecalendar로 설정되어있음을 알 수 있습니다!

spinner 타입의 DatePicker

DatePicker를 스피너 타입으로 주었을 때는 스피너를 통해 사용자가 직접 날짜를 입력할 수 있게 해줍니다.

이렇게 스피너로부터 날짜를 입력받을 수 있습니다.

이 때는

<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:datePickerModespinner로 주면 됩니다.

값 얻어오기

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 함수를 오버라이드 해주었습니다.

파라미터로 받아온 뷰(버튼)이 클릭되었을 때 텍스트뷰를 사용자가 지정한 날짜로 바꿔줍니다.


TimePicker


개요

시간을 선택할 수 있게 해주는 컴포넌트입니다.

마찬가지로 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"
/>

timePickerModeclock으로 설정되어 있습니다.

spinner 타입의 TimePicker

DatePicker와 마찬가지로 목록에서 직접 시간을 선택할 수 있게 해주는 spinner 타입도 제공합니다.

코드에서 timePickerModespinner로 바꿔주면

<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를 별도로 선언해서 텍스트뷰에 집어넣어주면 됩니다.

profile
tried ? drinkCoffee : keepGoing;

0개의 댓글