이 글은 Android12 및 코틀린 완전 정복을 참고하여 작성하였습니다.
작성자 : 윤승민
개발환경은 Mac, Android Studio입니다.
준비
분 단위 나이 계산기는 사용자가 버튼을 클릭하여 나타나는 캘린더에서 날짜를 선택하면 분 단위의 시간을 알려준다. 이를 구현하기 위해서는 사용자와 상호작용할 Button과 TextView가 필요하며 버튼을 눌렀을 때 캘린더가 화면에 표시되어 사용자가 원하는 날짜를 선택하게끔 하게 해주는 DatePickerDialog가 필요하다.
레이아웃 XML
첫 번째는 사용자에게 보여줄 화면이다. 위에서 말했듯이 Button, TextView 이렇게 두 가지가 필요하다. XML파일을 만들어보면 다음과 같다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/bgColor"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="16dp"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="CALCULATE YOUR"
android:textColor="@color/textBlue"
android:textSize="25sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@color/textBlue"
android:padding="10dp"
android:text="AGE"
android:textColor="@color/white"
android:textSize="25sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:padding="10dp"
android:text="IN MINUTES"
android:textColor="@color/textBlue"
android:textSize="25sp"
android:textStyle="bold" />
<Button
android:id="@+id/btnDatePicker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="@color/btnBgColor"
android:text="SELECT DATE"
android:textColor="@color/lightGray" />
<TextView
android:id="@+id/tvSelectedDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="31.05.1988"
android:textColor="@color/textBlue"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Selected Date"
android:textColor="@color/lightGray"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tvAgeInMinutes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="14000000"
android:textColor="@color/textBlue"
android:textSize="30sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Selected Date"
android:textColor="@color/lightGray"
android:textSize="20sp"
android:textStyle="bold" />
</LinearLayout>
뭔가 텍스트 뷰가 굉장히 많지만 id를 가진 텍스트 뷰만 사용할 것이다. 그리고 버튼도 생성해서 id를 부여해준다.
안드로이드의 UI 생성 방법은 위의 XML파일로 만들어서 화면에 보이게 하는 방법과 직접 코드로 입력해서 생성하는 방법이 있다. 그리고 XML 파일로 레이아웃과 뷰들을 정의해도 따로 코드를 통한 불러오기가 가능하다. 따라서 이러한 특징을 이용해 사용자가 버튼을 클릭했을 때 캘린더가 나타나도록 코드를 작성하면 된다.
뷰를 코드로 불러오려면 다음과 같이 id를 부여해주면 된다.
<Button
android:id="@+id/btnDatePicker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="@color/btnBgColor"
android:text="SELECT DATE"
android:textColor="@color/lightGray" />
<TextView
android:id="@+id/tvSelectedDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="31.05.1988"
android:textColor="@color/textBlue"
android:textSize="20sp"
android:textStyle="bold" />
액티비티에 레이아웃 XML을 연결
이제 레이아웃 XML을 다 만들었으니 액티비티와 연결해서 사용하기만 하면 된다.
액티비티의 onCreate함수 내에 들어있는 setContentView가 이러한 역할을 한다. onCreate 함수는 앱 실행시 처음 시작 단계이며 한 번 실행된다. 이 때 레이아웃 XML을 액티비티와 연결시킨다. 연결이 됐으니 이제 버튼을 액티비티에 불러오기만 하면 된다.
액티비티에 뷰를 사용하고 싶다면 findViewById를 통해 원하는 뷰를 아이디로 찾으면 된다.
private var tvSelectedDate : TextView? = null
private var tvAgeInMinutes : TextView? = null
val btnDatePicker : Button = findViewById(R.id.btnDatePicker)
tvSelectedDate = findViewById(R.id.tvSelectedDate)
tvAgeInMinutes = findViewById(R.id.tvAgeInMinutes)
뷰를 성공적으로 액티비티에 불렀으니 이제 액티비티 내에서 뷰가 가진 속성들을 다룰 수 있다.
그 중에서 버튼은 클릭했을 때 캘린더를 펼쳐야 하므로 클릭 이벤트에 대한 코드를 작성해보자.
btnDatePicker.setOnClickListener {
clickDatePicker()
}
setOnClickListener는 이름 그대로 버튼을 클릭했을 때 어떤 동작을 할지 설정하면 된다. 캘린더를 꺼내는게 목표이므로 캘린더를 꺼내는 함수를 하나 만들어서 안에다 호출을 해주면 된다.
DatePickerDialog
clickDatePicker 함수의 내용은 다음과 같다.
val myCalendar = Calendar.getInstance()
val year = myCalendar.get(Calendar.YEAR)
val month = myCalendar.get(Calendar.MONTH)
val day = myCalendar.get(Calendar.DAY_OF_MONTH)
val dpd = DatePickerDialog(this, { view, selectedYear, selectedMonth, selectedDayOfMonth ->
// 리스너 코드 작성 부분
},
year,
month,
day
)
DatePickerDialog라는 객체를 이용하면 캘린더를 구현할 수 있다. 이름 그대로 다이얼로그 형태로 캘린더가 사용자에게 보이게 된다. 이를 만드려면 다음과 같은 준비가 필요하다.
1. 캘린더를 다이얼로그 형태로 출력할 화면
- 메인 액티비티에 캘린더를 띄울 것이므로 현재 액티비티를 뜻하는 this를 넘긴다.
2. 사용자가 원하는 날짜를 선택했을 때 원하는 동작을 정의한 리스너
3. 현재에 대한 정보(년, 월, 일)
이것을 DatePickerDialog의 인자로 넘겨주면 캘린더 생성이 끝난다. 생성이 완료되고 show 메소드를 호출하면 캘린더가 화면에 나타난다.
SimpleDateFormat
레이아웃도 만들었고 이를 액티비티에 연결해서 버튼을 눌렀을 때 동작까지 만들었다. 사용자는 이제 신나게 캘린더 내에서 날짜를 고를 수 있다. 그런데 원하는 날짜를 선택하고 확인을 눌렀을 때의 동작을 아직 정의하지 않았다. 여기까지 해줘야 분 단위 나이 계산기가 완성이 된다. 분 단위로 계산은 SimpleDateFormat을 이용한다.
SimpleDateFormat은 현재 문자열을 파싱하여 Date 형태로 반환해준다.
날짜 정보가 담긴 문자열의 형태에 맞춰서 패턴을 정해줘야 한다.
val selectedDate = "$selectedDayOfMonth/${selectedMonth+1}/$selectedYear"
val sdf = SimpleDateFormat("dd/MM/yyyy", Locale.KOREA)
val theDate = sdf.parse(selectedDate)
selectedDate 의 문자열 형식에 맞춰서 SimpleDateFormat에 패턴을 지정한다.
이를 파싱하여 Date형태로 만든 뒤에 시간 정보를 불러오면 된다.
val selectedDate = "$selectedDayOfMonth/${selectedMonth+1}/$selectedYear"
val sdf = SimpleDateFormat("dd/MM/yyyy", Locale.KOREA)
val theDate = sdf.parse(selectedDate)
theDate?.let{
val selectedDateInMinutes = theDate.time / 60000
val currentDate = sdf.parse(sdf.format(System.currentTimeMillis()))
tvSelectedDate?.text = currentDate.toString()
val currentDateInMinutes = currentDate!!.time / 60000
val differenceInMinutes = currentDateInMinutes - selectedDateInMinutes
tvAgeInMinutes?.text = differenceInMinutes.toString()
위처럼 theDate의 time(ms 기준)을 불러와서 분 단위로 바꿔주면 된다.
3600초를 분 단위로 바꿔주려면 60초를 나눠주면 된다. 밀리 초도 마찬가지다.
1s = 1000ms
60s = 60000ms
따라서 60000으로 나눠주면 분 단위의 결과값이 나오게 된다. 구한 값을 마지막에 텍스트 뷰의 속성인 setText를 통해 텍스트 뷰의 텍스트 값을 변경해주면 완성이다. 이 코드는 DatePickerDialog의 인자로 넘기는 리스너의 내용으로 삽입하면 된다. 그렇게 하면 사용자가 날짜를 선택하고 확인을 할 때마다 위의 코드가 실행되어 분 단위로 텍스트 뷰를 통해 분 단위 나이 결과값을 확인할 수 있다.
이제 모든 준비가 끝났으므로 DatePickerDialog의 show 메소드를 호출해서 화면에 띄우기만 하면 끝이다.
전체 코드
package com.example.myapplication
import android.app.DatePickerDialog
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import java.text.SimpleDateFormat
import java.util.*
class MainActivity : AppCompatActivity() {
private var tvSelectedDate : TextView? = null
private var tvAgeInMinutes : TextView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val btnDatePicker : Button = findViewById(R.id.btnDatePicker)
tvSelectedDate = findViewById(R.id.tvSelectedDate)
tvAgeInMinutes = findViewById(R.id.tvAgeInMinutes)
btnDatePicker.setOnClickListener {
clickDatePicker()
}
}
private fun clickDatePicker() {
val myCalendar = Calendar.getInstance()
val year = myCalendar.get(Calendar.YEAR)
val month = myCalendar.get(Calendar.MONTH)
val day = myCalendar.get(Calendar.DAY_OF_MONTH)
val dpd = DatePickerDialog(this, { view, selectedYear, selectedMonth, selectedDayOfMonth ->
Toast.makeText(this,
"Year was $selectedYear, month was ${selectedMonth+1}, day of Month $selectedDayOfMonth", Toast.LENGTH_SHORT).show()
val selectedDate = "$selectedDayOfMonth/${selectedMonth+1}/$selectedYear"
val sdf = SimpleDateFormat("dd/MM/yyyy", Locale.KOREA)
val theDate = sdf.parse(selectedDate)
theDate?.let{
val selectedDateInMinutes = theDate.time / 60000
val currentDate = sdf.parse(sdf.format(System.currentTimeMillis()))
tvSelectedDate?.text = currentDate.toString()
val currentDateInMinutes = currentDate!!.time / 60000
val differenceInMinutes = currentDateInMinutes - selectedDateInMinutes
tvAgeInMinutes?.text = differenceInMinutes.toString()
}
},
year,
month,
day
)
dpd.datePicker.maxDate = System.currentTimeMillis() - 86400000 // 하루 24시간을 ms로 표현하면 86400000, 선택할 수 있는 가장 최근의 날짜를 현재를 기준으로 하루 전으로 설정
dpd.show()
}
}
'GDSC HUFS 4기 > Kotlin Team #4' 카테고리의 다른 글
[4팀] 퀴즈 앱 안드로이드 12 후반부 (0) | 2022.11.09 |
---|---|
[4팀]계산기 - XML사용법과 UI 생성법 배우기 (0) | 2022.11.08 |
[4팀] 코틀린 기능 더 배우기 (0) | 2022.10.10 |
[4팀] 코틀린 객체 지향 프로그래밍 기초 (0) | 2022.10.10 |
[4팀] 코틀린 기초 (0) | 2022.10.02 |