라이브러리 소개
GitHub - kizitonwose/Calendar: A highly customizable calendar view and compose library for Android.
A highly customizable calendar view and compose library for Android. - GitHub - kizitonwose/Calendar: A highly customizable calendar view and compose library for Android.
github.com
여러가지 캘린더 라이브러리를 찾아보다가 해당 라이브러리를 찾게 되었다. 해당 라이브러리의 장점으로는 커스텀이 매우 자유롭고 방법도 쉽다.
또한, 라이브러리 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 |