이번 7/1-7/2에 진행된 umc 해커톤에서 우리 팀 어플의 핵심기능 중 하나인 ✨범위 형태로 날짜를 선택 후 리사이클러뷰로 출력✨을 맡아 구현하게 되었다.
덕분에 여러가지 커스텀된 캘린더뷰를 직접 사용해보고 연습해 볼 수 있었고, 캘린더뷰에 대해 공부를 정말 깊게 했다. 그리고 내가 원하는 형태로 커스텀된 캘린더도 찾을 수 있었다!
내가 원하던 형태로 커스텀 되어있는 CosmoCalendar를 사용했다 🙌
📌 깃허브
https://github.com/koominji/CustomCalendar_umc_hackathon
velog는 동영상 첨부가 안되나..;?
range 형태로 날짜를 선택할 수 있는 CosmoCalendar를 사용했다.
// cosmoCalendar
implementation 'com.github.applikeysolutions:cosmocalendar:1.0.4'
<!-- cosmo calendar -->
<com.applikeysolutions.cosmocalendar.view.CalendarView
android:id="@+id/calendar_view"
android:layout_width="match_parent"
android:layout_height="500dp"
app:connectedDayIconPosition="top"
app:currentDayIconRes="@drawable/round_shape_img"
app:currentDaySelectedIconRes="@drawable/border_top_bottom"
app:currentDayTextColor="@color/appMainColor"
app:firstDayOfTheWeek="sunday"
app:layout_constraintTop_toTopOf="parent"
app:orientation="horizontal"
app:selectedDayBackgroundColor="@color/appMainColor"
app:selectedDayBackgroundEndColor="@color/appMainColor"
app:selectedDayBackgroundStartColor="@color/appMainColor"
app:selectedDayTextColor="#FFFFFF"
app:selectionType="range"
app:weekendDayTextColor="#ef4550" />
여기서 중요한건 ✨selectionType✨
CosmoCalendar 여기서도 확인가능하지만,
등등 다양한 형태로 선택이 가능하다
binding.calendarView.isShowDaysOfWeekTitle = false
binding.calendarView.selectionManager = RangeSelectionManager(OnDaySelectedListener {
if (binding.calendarView.selectedDates.size <= 0) return@OnDaySelectedListener
Log.d("selected dates", "${binding.calendarView.selectedDays}")
})
class SelectedDatesRVAdapter(val dates:List<Day>) : RecyclerView.Adapter<SelectedDatesRVAdapter.ViewHolder>() {
inner class ViewHolder(val binding: CreateSelectedDateRvItemBinding):RecyclerView.ViewHolder(binding.root){
fun bind(dates: Day){
var temp=dates.toString()
Log.d("selectedDate",temp)
binding.selectedDateMonth.text= temp.slice(11..14) //월
binding.selectedDateDay.text= temp.slice(15..17) //일
binding.selectedDateDayOfWeek.text= temp.slice(8..11) //요일
}
}
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
val binding:CreateSelectedDateRvItemBinding= CreateSelectedDateRvItemBinding.inflate(LayoutInflater.from(viewGroup.context),viewGroup,false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val binding = (holder as SelectedDatesRVAdapter.ViewHolder).binding
holder.bind(dates[position])
binding.selectedDateRvRoot.setOnClickListener {
Log.d("clicked","${position}")
}
}
override fun getItemCount(): Int = dates.size
}
허허........
fun bind(dates: Day){
var temp=dates.toString()
Log.d("selectedDate",temp)
binding.selectedDateMonth.text= temp.slice(11..14) //월
binding.selectedDateDay.text= temp.slice(15..17) //일
binding.selectedDateDayOfWeek.text= temp.slice(8..11) //요일
}
음 이건 뭐냐면,,선택된 날짜를 Log로 보니 이런 모습이길래 👇
필요한 월, 일, 요일 부분만 무식하게 슬라이싱했다 ㅎㅋㅎㅋ😅 하면서도 절대 좋은 방법은 아니라는 생각이 들었다,,, 그냥 임시방편,,ㅋㅅㅋ 일단 해커톤에서는 시간이 없으니 이렇게 했는데
(안드 개발하면서 동시에 pm이여서 진짜 너무 정신없엇다,,)
앞으로 이 부분에서 서버랑 협업도 해야하고 다른 기능 구현할것도 고려해서
👉 이 부분은 해커톤 이후에 !!!!꼭!!!! 바꿔야지 생각했음 👈
class SelectedDatesRVAdapter(val dates:List<Day>) : RecyclerView.Adapter<SelectedDatesRVAdapter.ViewHolder>() {
inner class ViewHolder(val binding: CreateSelectedDateRvItemBinding):RecyclerView.ViewHolder(binding.root){
fun bind(dates: Day){
val year = dates.calendar.get(YEAR)
val month = dates.calendar.get(MONTH)+1
val day = dates.calendar.get(DAY_OF_MONTH)
val dayOfWeek = dates.calendar.getDisplayName(DAY_OF_WEEK, LONG_FORMAT, Locale.KOREAN)
binding.selectedDateMonth.text= month.toString()+"월" //월
binding.selectedDateDay.text= day.toString() //일
binding.selectedDateDayOfWeek.text= dayOfWeek //요일
}
}
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
val binding:CreateSelectedDateRvItemBinding= CreateSelectedDateRvItemBinding.inflate(LayoutInflater.from(viewGroup.context),viewGroup,false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val binding = (holder as SelectedDatesRVAdapter.ViewHolder).binding
holder.bind(dates[position])
binding.selectedDateRvRoot.setOnClickListener {
Log.d("clicked","${position}")
}
}
override fun getItemCount(): Int = dates.size
}
이렇게 수정했다 👇🤩
fun bind(dates: Day){
val year = dates.calendar.get(YEAR)
val month = dates.calendar.get(MONTH)+1
val day = dates.calendar.get(DAY_OF_MONTH)
val dayOfWeek = dates.calendar.getDisplayName(DAY_OF_WEEK, LONG_FORMAT, Locale.KOREAN)
binding.selectedDateMonth.text= month.toString()+"월" //월
binding.selectedDateDay.text= day.toString() //일
binding.selectedDateDayOfWeek.text= dayOfWeek //요일
}
Log.d("dayOfWeek",dates.calendar.get(DAY_OF_WEEK).toString())
로 확인해보면
월요일 : 1
화요일 : 2
수요일 : 3
목요일 : 4
금요일 : 5
토요일 : 6
일요일 : 7
DAY_OF_WEEK 는 요일별로 int 형으로 return 되는데
🤔 이걸 바로 요일로 출력할수는 없나..? 🤔 싶어 찾아보니
dates.calendar.getDisplayName(DAY_OF_WEEK, LONG_FORMAT, Locale.KOREAN)
👉 getDisplayName 을 사용하면 바로 요일을 출력할 수 있다 👍
lateinit var dates: List<Day>
override fun onCreate(savedInstanceState: Bundle?) {
// (중략)
// 선택된 dates
dates = binding.calendarView.selectedDays
// 선택된 날짜 recyclerview
val selectedDatesRVAdapter = SelectedDatesRVAdapter(dates)
binding.createSelectedDateRv.adapter = selectedDatesRVAdapter
val selectedDatesLayoutManager = LinearLayoutManager(this)
selectedDatesLayoutManager.orientation = LinearLayoutManager.HORIZONTAL
binding.createSelectedDateRv.layoutManager = selectedDatesLayoutManager
// (중략)
}
calendarView.selectedDays
로 선택된 날짜를 받아온다
👉 선택된 모든 날짜가 List<Day>
형태로 return 된다
그렇기 때문에 선택된 날짜를 넣을 lateinit var dates: List<Day>
또한 List<Day>
형태로 선언한다
cf. RVAdapter 에서도 class SelectedDatesRVAdapter(val dates:List<Day>) : ....
🤔 평소에 arrayList,mutableListOf 만 주로 사용했는데 List는 좀 낯설었다
캘린더에 대해 정말정말정말 많이 공부했고 역시 프로젝트하면서 제일 많이 배우고 빠르게 성장한다고 생각했다 .......... ! 👩💻
벨로그에 글 처음쓰는데 이런거 써놓으면 누군가에게 도움이 되려나 ㅎㅅㅎ 암튼 끝!