라이브러리 소개
여러가지 캘린더 라이브러리를 찾아보다가 해당 라이브러리를 찾게 되었다. 해당 라이브러리의 장점으로는 커스텀이 매우 자유롭고 방법도 쉽다.
또한, 라이브러리 Readme 자체에 설명이 정말 잘 되어 있어서 쉽게 따라하고 적용할 수 있었다.
이번 프로젝트에선 구글 캘린더처럼 아래로 내리면 펼쳐지고, 위로 올리면 1줄 달력이 되는 캘린더를 구현하려고 하고 있기에, 커스텀이 자유로운 해당 라이브러리가 적절할 것 같다.
기본 사용법
1. 캘린더 뷰 적용하기
1. XML 작성
app:cv_dayViewResource 속성은 필수로 지정해야한다. 지정하지 않을 경우, 앱이 강제 종료 된다.
<com.kizitonwose.calendar.view.CalendarView
android:id="@+id/calendarView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cv_dayViewResource="@layout/calendar_day_layout" />
2. 캘린더 셀(Cell) 레이아웃 생성
달력의 한 칸을 나타낼 레이아웃을 res/layout/calendar_day_layout.xml 에 생성한다.
해당 레이아웃을 커스텀하여 자유롭게 달력의 한 칸을 꾸밀 수 있다.
<TextView
android:id="@+id/calendarDayText"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="16sp"
tools:text="22" />
3. 캘린더 셀(Cell) 바인딩
DayViewContainer 클래스를 생성하여 위에서 지정한 셀의 뷰를 바인딩 해준다. DayViewContainer 클래스는 날짜 셀에 대한 뷰 홀더 역할을 하는 클래스이다.
여기서 날짜 셀을 클릭했을 때의 이벤트 리스너도 등록할 수 있다.
class DayViewContainer(view: View) : ViewContainer(view) {
val textView = view.findViewById<TextView>(R.id.calendarDayText)
// With ViewBinding
// val textView = CalendarDayLayoutBinding.bind(view).calendarDayText
}
class DayViewContiner(view: View) : ViewContainer(view){
// MonthDayBinder에서 해당 변수에 data(CalendarDay)를 넣어줄 예정
lateinit var day: CalendarDay
val textView = view.findViewById<TextView>(R.id.dayTextView)
init {
view.setOnClickListener {
// 날짜를 클릭했을 때 이벤트
Log.d("CollapisbleActivity", day.toString())
}
}
}
DayViewContainer 클래스를 작성했으면, calendarView의 dayBinder에 MonthDayBinder 인터페이스를 구현하여 할당한다.
calendarView.dayBinder = object : MonthDayBinder<DayViewContainer> {
// 새 컨테이너가 필요할 때만 호출
override fun create(view: View) = DayViewContainer(view)
// 컨테이너가 재사용될 때마다 호출
override fun bind(container: DayViewContainer, data: CalendarDay) {
// DayViewContainer의 day 변수에 data 할당
container.day = data
container.textView.text = data.date.dayOfMonth.toString()
}
}
create() 메소드의 반환 값으로 방금 생성한 DayViewContainer(view) 클래스를 지정한다. 그럼 캘린더의 각 셀에 뷰가 내가 지정한 레이아웃으로 만들어지게 된다.
bind() 메소드에선 셀 내의 뷰들에 대한 값을 세팅해준다. 달력 밑에 점을 통해서 일정을 표시하는 경우가 많은데, 그런 경우에도 이 bind() 메소드에서 작업해주면 될 것 같다.
4. 캘린더 뷰 초기화
위의 작업들은 레이아웃을 지정하고, 바인딩하는 과정이었다. 위의 작업들만 한다고 해서 캘린더가 표시되는 것은 아니다.
calendarView.apply {
val currentMonth = YearMonth.now()
val firstMonth = currentMonth.minusMonths(240)
val lastMonth = currentMonth.plusMonths(240)
val firstDayOfWeek = firstDayOfWeekFromLocale()
setup(firstMonth, lastMonth, firstDayOfWeek)
scrollToMonth(currentMonth)
}
2. 요일 타이틀 만들기
아래는 요일을 생성하는 메소드다.
val daysOfWeek = daysOfWeek() // 라이브러리 내의 메소드
만약, 요일의 시작을 바꾸고 싶다면 아래와 같이 작성하면 된다.
// Thu | Fri | Sat | Sun | Mon | Tue | Wed
val daysOfWeek = daysOfWeek(firstDayOfWeek = DayOfWeek.THURSDAY)
1. 요일 타이틀 레이아웃 생성
요일의 텍스트가 들어갈 레이아웃을 res/layout/calendar_day_title_text.xml에 생성한다.
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center" />
요일들을 담을 타이틀 레이아웃을 생성한다.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="7"
android:orientation="horizontal">
<!-- 하나하나가 요일을 나타내는 텍스트 뷰이다. -->
<include layout="@layout/calendar_day_title_text" />
<include layout="@layout/calendar_day_title_text" />
<include layout="@layout/calendar_day_title_text" />
<include layout="@layout/calendar_day_title_text" />
<include layout="@layout/calendar_day_title_text" />
<include layout="@layout/calendar_day_title_text" />
<include layout="@layout/calendar_day_title_text" />
</LinearLayout>
CalendarView 위에 include 해주면, 요일 타이틀이 완성된다.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include
android:id="@+id/titlesContainer"
layout="@layout/calendar_day_titles_container" />
<com.kizitonwose.calendar.view.CalendarView
android:id="@+id/calendarView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cv_dayViewResource="@layout/calendar_day_layout" />
</LinearLayout>
2. 요일 할당하기
이전에 생성한 요일을 담고 있는 타이틀 레이아웃의 children이 각각의 요일을 뜻한다.
각 요일 TextView에 요일을 할당한다.
titlesContainer.children
.map { it as TextView }
.forEachIndexed{ idx, textView ->
val dayOfWeek = daysOfWeek()[idx]
val title = dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.getDefault())
textView.text = title
}
실행 결과
여기까지 적용하면 아래와 같은 화면이 완성된다. 다음 포스트에선 해당 라이브러리의 속성, 메소드 등을 정리해보고, 그 후에 캘린더를 커스텀하여 예쁘게 꾸며볼 예정이다.
'안드로이드' 카테고리의 다른 글
[ 안드로이드 ] 구글 캘린더 구현하기 (3) - 캘린더 Week <-> Month 전환 구현 (0) | 2023.02.28 |
---|---|
[ 안드로이드 ] 구글 캘린더 구현하기 (2) - CalendarView 라이브러리 속성 정리 (0) | 2023.02.28 |
[ 안드로이드 ] 멘토링 과제 1. (1) | 2023.02.13 |