일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 부스트코스에이스
- 막내의막무가내 안드로이드 코틀린
- 막내의막무가내 안드로이드
- 프로그래머스 알고리즘
- 막내의막무가내 플러터
- 막내의막무가내 플러터 flutter
- 막내의막무가내 프로그래밍
- 막내의막무가내 일상
- 막내의막무가내 코볼 COBOL
- 2022년 6월 일상
- 안드로이드
- flutter network call
- 막내의막무가내 안드로이드 에러 해결
- 부스트코스
- 막내의 막무가내 알고리즘
- 막내의막무가내 코틀린
- 막내의막무가내 알고리즘
- Fragment
- 안드로이드 Sunflower 스터디
- 막무가내
- 주엽역 생활맥주
- 주택가 잠실새내
- 막내의막무가내
- 막내의막무가내 코틀린 안드로이드
- 막내의막무가내 목표 및 회고
- 막내의막무가내 rxjava
- 막내의 막무가내
- 막내의막무가내 SQL
- 프래그먼트
- 안드로이드 sunflower
- Today
- Total
막내의 막무가내 프로그래밍 & 일상
[안드로이드] Android Material Calendar View 사용법 정리 본문
[2021-04-14 업데이트]
달력 라이브러리와 사용법에 대한 정리입니다 ㅎㅎ
지금까지 기본 캘린더뷰 부터 시작해서 총 3가지 정도의 캘린더 뷰를 사용해봤는데요.
오늘 다룰 것은 다음 캘린더뷰 라이브러리 입니다.
github.com/prolificinteractive/material-calendarview
자세한 방법은 해당 깃허브에 들어가도 나오므로 저는 간략하게 사용한 것을 기록하려고 합니다.
1. dependency 추가
implementation 'com.github.prolificinteractive:material-calendarview:2.0.1'
2. xml
선택 모드, 주단위 월단위. 색상 등을 변경할 수 있습니다. (app:mcv_)
<com.prolificinteractive.materialcalendarview.MaterialCalendarView
android:id="@+id/cv_calendar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/view_date"
app:mcv_selectionColor="#f79256"
app:mcv_selectionMode="range" />
3. 코드
저같은 경우 range(범위) 선택 모드일 경우를 구현 했습니다. 주의하실 점은 범위 모드일 경우 날짜를 두 개 클릭해서 범위가 되지 않으면 setOnRangeSelectedListener 로 콜백이 안오므로 하나만 클릭 했을 경우를 대비해 setOnDateChangedListener 를 추가로 사용했습니다.
두 리스너를 간단히 설명하면
setOnRangeSelectedListener-> 처음 날짜와 두번 째 날짜를 선택한 경우(범위지정 한 경우) 콜백이 오고 해당 범위의 날짜들이 리스트로(dates) 온다.
widget, dates ->
setOnDateChangedListener-> 처음 날짜를 선택한 경우 해당 날짜(date) 콜백이온다. Range모드 일떄 두번째 날짜 선택시에는 콜백이 안오고 setOnRangeSelectedListener 에만 콜백이 온다. 범위 지정이 되어있는 경우 해당 범위지정된 날짜를 다시 한번 클릭하면 범위지정이 취소되는데 그때도 여기로 setOnDateChangedListener 콜백이 온다.
widget, date, selected ->
첫번째 날짜 선택했을때 콜백과 다른점은 selected 가 첫 날짜 선택시에는 true 범위지정된 날짜를 다시 한번 누른 경우는 false 로 넘어 온다는 점이다.
그리고 setOnRangeSelectedListener 의 경우 시작날짜와 선택날짜를 선택한 경우 콜백이 올텐데 이 범위에 있는 날짜들을 모두 포함한 CalendarDay 라는 타입의 리스트로 오게 됩니다.
저 같은 경우 확장함수를 하나 만들어 해당 2020-1-2 이런 날짜를 타임스탬프로 변환해주는 함수를 만들어 Long 형으로 변환하는 작업을 추가로 했습니다. (밑에 첨부해놨습니다.)
binding.cvCalendar.setOnRangeSelectedListener { widget, dates ->
if (!viewModel.checkDatesAvailable(dates)) {
showToast(getString(R.string.date_can_not_selected_msg))
binding.cvCalendar.clearSelection()
viewModel.initDateRange()
return@setOnRangeSelectedListener
}
viewModel.setStartDateTimestamp(dates[0])
if (dates.size == 0) {
viewModel.setEndDateTimestamp(dates[dates.size])
} else if (dates.size != 1) {
viewModel.setEndDateTimestamp(dates[dates.size - 1])
}
viewModel.setDateRange()
}
binding.cvCalendar.setOnDateChangedListener { widget, date, selected ->
val calList = ArrayList<CalendarDay>()
calList.add(date)
when {
!selected -> {
viewModel.initDateRange()
viewModel.isDateSelected = false
viewModel.setAllSelected()
}
!viewModel.checkDatesAvailable(calList) -> {
showToast(getString(R.string.date_can_not_selected_msg))
binding.cvCalendar.clearSelection()
viewModel.initDateRange()
}
else -> {
viewModel.setStartDateTimestamp(date)
viewModel.setEndDateTimestamp(date)
viewModel.isDateSelected = selected
viewModel.setAllSelected()
viewModel.setSingleDateRange()
}
}
}
// 2020, 1, 20 -> timestamp
fun convertDateToTimestamp(_year: Int, _month: Int, _day: Int): Long {
val month = _month.toString().convertSingleToDoubleDigit().toInt()
val day = _day.toString().convertSingleToDoubleDigit().toInt()
val date = "$_year-$month-$day"
return date.convertDateToTimestamp()
}
// 한자리 숫자면 두자리로 변환
fun String.convertSingleToDoubleDigit(): String = if (this.length < 2) "0$this" else this
// 날짜만 타임스탬프 변환 2020-01-01 - timestamp
fun String.convertDateToTimestamp(): Long =
SimpleDateFormat("yyyy-MM-dd", Locale.KOREA).parse(this).time
3. 최소날짜 최대 날짜
최소날짜와 최대날짜도 지정할 수 있습니다. 저는 오늘 이하 날짜를 막기 위해 다음과 같이 지정하였습니다.
binding.cvCalendar.state().edit()
.setMinimumDate(
CalendarDay.from(
getCurrentYear(),
getCurrentMonth(),
getCurrentDay() + 1
)
)
.setCalendarDisplayMode(CalendarMode.WEEKS)
.commit()
// 현재 Year
fun getCurrentYear(): Int = Calendar.getInstance().get(Calendar.YEAR)
// 현재 Month
fun getCurrentMonth(): Int = Calendar.getInstance().get(Calendar.MONTH) + 1
// 현재 Day
fun getCurrentDay(): Int = Calendar.getInstance().get(Calendar.DAY_OF_MONTH)
4. 3번의 경우 특정 하나의 범위만 막을 수 있습니다. 만약 여러개의 범위 또는 날짜를 막고 싶다면 다음과 같이 Decorator 클래스를 하나만들어 커스텀 할 수 있습니다. 선택을 막을 수도 있고 아이콘이나 배경색을 바꿀 수도 있습니다.
다음과 같이 샘플을 하나 짜봤씁니다.
DayViewDecorator 를 상속받는 커스텀 클래스 생성 (저의 경우 해당 날짜의 선택을 막게하고 X표시 이미지로 했습니다.)
주의할 점은 해당 setDaysDisabled 는 해당 날짜의 선택만 막게하고 범위지정은 못 막습니다.
예를들면 14 ~ 15일이 예약이 차있고 setDaysDisabled 로 설정한 경우 해당 날짜 선택은 막을 수 있지만 13일을 누르고 16일 누르는 range(범위) 선택을 하는 경우는 범위에 포함되는 것을 못 막습니다. 이 점은 따로 처리를 해주어야 했습니다.
package com.mtjin.nomoneytrip.views.reservation_phase_first
import android.R
import android.app.Activity
import android.graphics.drawable.Drawable
import com.mtjin.nomoneytrip.utils.getMyDrawable
import com.prolificinteractive.materialcalendarview.CalendarDay
import com.prolificinteractive.materialcalendarview.DayViewDecorator
import com.prolificinteractive.materialcalendarview.DayViewFacade
class CurrentDayDecorator(context: Activity?, currentDay: CalendarDay) : DayViewDecorator {
private val drawable: Drawable = context?.getMyDrawable(R.drawable.ic_menu_close_clear_cancel)!!
private var myDay = currentDay
override fun shouldDecorate(day: CalendarDay): Boolean {
return day == myDay
}
override fun decorate(view: DayViewFacade) {
//view.setSelectionDrawable(drawable!!)
view.setBackgroundDrawable(drawable)
view.setDaysDisabled(true)
}
init {
// You can set background for Decorator via drawable here
}
}
프래그먼트와 액티비티에 추가
val calList = ArrayList<CalendarDay>()
calList.add(CalendarDay.from(2020, 9, 20))
calList.add(CalendarDay.from(2020, 9, 21))
calList.add(CalendarDay.from(2020, 9, 22))
calList.add(CalendarDay.from(2020, 9, 23))
for (calDay in calList){
binding.cvCalendar.addDecorators(CurrentDayDecorator(requireActivity(),calDay))
}
그럼 해당 날짜들이 선택을 못하게됩니다.
[결과 사진]
실제 프로젝트의 이미지입니다.
이 상
prolificinteractive/material-calendarview
에 대해 알아봤습니다.
댓글과 공감은 큰 힘이 됩니다. 감사합니다. !!
출처 :
'안드로이드 > 코틀린 & 아키텍처 & Recent' 카테고리의 다른 글
[안드로이드] 안드로이드 CollapsingToolbarLayout UI 기록 (2) | 2020.09.19 |
---|---|
[안드로이드] WebView Sample 정리 및 프래그먼트에서 뒤로가기시 웹뷰 스택사용하기 (0) | 2020.09.12 |
[안드로이드] 안드로이드 BottomSheetDialog 샘플 (with top radius)(feat. 네 아니요 질문, Ratingbar 점수주기) (0) | 2020.09.08 |
[안드로이드] Android Tmap 사용법 간략 정리(feat 지도위치, 마커, 길찾기) (0) | 2020.09.07 |
[안드로이드] 새로운 저장소 Jetpack DataStore (feat. Sharedpreferences 를 대체) (2) | 2020.09.03 |