[Android Studio] MaterialCalendarView 커스텀해서 사용하기
안드로이드에서 기본 제공하는 CalendarView가 있습니다. 기본 CalendarView로는 다양한 커스텀을 하기 힘들기 때문에 다른 Calendar를 찾게 되는데요. 그 중 유명한 MaterialCalendarView에 대해 알아보겠습니다.
MaterialCalendarView는 안드로이드에서 기본 제공하는 CalendarView보다 많은 기능을 가지고 있기에 많은 사람들이 애용합니다.
이제 그 사용법과 활용방법을 알아보겠습니다.
build.gradle (Module:app) 에 추가해줍시다.
implementation 'com.prolificinteractive:material-calendarview:1.4.3'
이제 xml에 추가해줍시다.
<!--캘린더-->
<com.prolificinteractive.materialcalendarview.MaterialCalendarView
android:id="@+id/materialCalendar"
app:mcv_selectionColor="#d2d2d2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
mcv_selectionColor는 CalendarView에서 터치 시 나타나는 원의 색상을 지정하는 값입니다.
이제 kotlin 으로 넘어가 본격적으로 커스텀해보겠습니다.
var startTimeCalendar = Calendar.getInstance()
var endTimeCalendar = Calendar.getInstance()
val currentYear = startTimeCalendar.get(Calendar.YEAR)
val currentMonth = startTimeCalendar.get(Calendar.MONTH)
val currentDate = startTimeCalendar.get(Calendar.DATE)
endTimeCalendar.set(Calendar.MONTH, currentMonth+3)
materialCalendar.state().edit()
.setFirstDayOfWeek(Calendar.SUNDAY)
.setMinimumDate(CalendarDay.from(currentYear, currentMonth, 1))
.setMaximumDate(CalendarDay.from(currentYear, currentMonth+3, endTimeCalendar.getActualMaximum(Calendar.DAY_OF_MONTH)))
.setCalendarDisplayMode(CalendarMode.MONTHS)
.commit()
위 코드는 이번 달(6월)부터 3달 후(9월) 까지만 보여지도록 하는 예제입니다.
setMinimunDate / setMaximumDate로 사용자가 선택할 수 있는 최소 날짜와 최대 날짜를 설정할 수 있습니다.
MaterialCalendarView에서는 setMinimumDate를 설정하면 그 이전의 날짜는 아예 안보이게 됩니다.
.setMinimumDate(CalendarDay.from(currentYear, currentMonth, currentDate)
아래 사진은 setMinimumDate의 date를 오늘 날짜(26일)로 설정했을 때입니다.
위와 같이 아예 사라지기 때문에 minimumDate를 1일로 설정하고 오늘 이전의 날짜는 선택불가능 / 옅게 바꿔보겠습니다.
val stCalendarDay = CalendarDay(currentYear, currentMonth, currentDate)
val enCalendarDay = CalendarDay(endTimeCalendar.get(Calendar.YEAR), endTimeCalendar.get(Calendar.MONTH), endTimeCalendar.get(Calendar.DATE))
val sundayDecorator = SundayDecorator()
val saturdayDecorator = SaturdayDecorator()
val minMaxDecorator = MinMaxDecorator(stCalendarDay, enCalendarDay)
val boldDecorator = BoldDecorator(stCalendarDay, enCalendarDay)
val todayDecorator = TodayDecorator(this)
materialCalendar.addDecorators(sundayDecorator, saturdayDecorator, boldDecorator, minMaxDecorator, todayDecorator)
위와 같이 MaterialCalendar에는 직접 decorator를 만들어 추가할 수 있습니다.
위 Decorator들을 추가한 후의 상태입니다.
- todayDecorator로 오늘 날짜에 회색 테두리 설정
- sundayDecorator로 매주 일요일마다 빨간색으로 변경
- saturdayDecorator로 매주 토요일을 파란색으로 변경
- minMaxDecorator로 시작일(6월 26일), 종료일(9월26일)을 인자값으로 보내 해당 기간 바깥의 날짜들은 색을 연하게 하고 선택 불가능
- 마지막으로 boldDecorator로 시작일, 종료일 기간에 해당되는 날짜들의 크기를 키우고 진하게 변경
이제 이 Decorator 코드를 살펴보겠습니다.
TodayDecorator.kt
class TodayDecorator(context:Context):DayViewDecorator {
private var date = CalendarDay.today()
val drawable = context.resources.getDrawable(R.drawable.style_only_radius_10)
override fun shouldDecorate(day: CalendarDay?): Boolean {
return day?.equals(date)!!
}
override fun decorate(view: DayViewFacade?) {
view?.setBackgroundDrawable(drawable)
}
}
- shouldDecorate() : day가 today()와 같은지 확인 후 true라면 decorate()로 이동
- setBackgroundDrawable로 해당 view의 background 설정
SundayDecorator.kt / SaturdayDacorator.kt ( Calendar.SATURDAY & Color.BLUE )
class SundayDecorator:DayViewDecorator {
private val calendar = Calendar.getInstance()
override fun shouldDecorate(day: CalendarDay?): Boolean {
day?.copyTo(calendar)
val weekDay = calendar.get(Calendar.DAY_OF_WEEK)
return weekDay == Calendar.SUNDAY
}
override fun decorate(view: DayViewFacade?) {
view?.addSpan(object:ForegroundColorSpan(Color.RED){})
}
}
- weekDay : 어떤 요일인지 판별
- 일요일이라면 dacorate()로 이동
- view?.addSpan() 으로 해당 날짜의 색 변경
MinMaxDacorator.kt
class MinMaxDecorator(min:CalendarDay, max:CalendarDay):DayViewDecorator {
val maxDay = max
val minDay = min
override fun shouldDecorate(day: CalendarDay?): Boolean {
return (day?.month == maxDay.month && day.day > maxDay.day)
|| (day?.month == minDay.month && day.day < minDay.day)
}
override fun decorate(view: DayViewFacade?) {
view?.addSpan(object:ForegroundColorSpan(Color.parseColor("#d2d2d2")){})
view?.setDaysDisabled(true)
}
}
- minDay와 maxDay 설정 후 기간 외인지 판별
- 기간 외라면 날짜의 색 #d2d2d2로 변경 & 선택 불가능하게 변경
BoldDecorator.kt
class BoldDecorator(min:CalendarDay, max:CalendarDay):DayViewDecorator {
val maxDay = max
val minDay = min
override fun shouldDecorate(day: CalendarDay?): Boolean {
return (day?.month == maxDay.month && day.day <= maxDay.day)
|| (day?.month == minDay.month && day.day >= minDay.day)
|| (minDay.month < day?.month!! && day.month < maxDay.month)
}
override fun decorate(view: DayViewFacade?) {
view?.addSpan(object:StyleSpan(Typeface.BOLD){})
view?.addSpan(object:RelativeSizeSpan(1.4f){})
}
}
- minMaxDecorator와 마찬가지로 기간 설정
- 단, 기간이 3달이므로 가운데 껴있는 월(7,8월)도 포함
- 날짜의 Style, Size 변경
이외에 활용 방법은 Github 에서 확인할 수 있습니다.
https://github.com/prolificinteractive/material-calendarview
prolificinteractive/material-calendarview
A Material design back port of Android's CalendarView - prolificinteractive/material-calendarview
github.com