개발 끄적끄적/Android

[Android Studio] MaterialCalendarView 커스텀해서 사용하기

공간을담다 2020. 6. 26. 14:30
반응형

안드로이드에서 기본 제공하는 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

 

 

 

반응형