캘린더뷰 상단을 클릭하면 년/달 선택 메뉴가 나타나고 달에 해당하는 버튼을 누를 시에 해당 년/월로 한번에 이동하는 캘린더를 구현해 보았다.
이건 메뉴 부분을 xml로 디자인한 거다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:elevation="4dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_select_year"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
app:layout_constraintLeft_toLeftOf="@id/cl_month_group"
app:layout_constraintRight_toRightOf="@id/cl_month_group"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/iv_prev_year"
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/chevron_left"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_year"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/pretendard_bold"
android:text=""
android:textColor="@color/black"
android:textSize="26sp"
android:layout_marginHorizontal="75dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/iv_prev_year"
app:layout_constraintRight_toLeftOf="@id/iv_next_year"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/iv_next_year"
android:layout_width="24dp"
android:layout_height="24dp"
android:src="@drawable/chevron_right"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_month_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="18dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_select_year">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_month_group1"
android:layout_width="309dp"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<Button
android:id="@+id/btn_month_1"
android:layout_width="99dp"
android:layout_height="38dp"
android:background="@drawable/button_design_gray_50"
android:text="1월"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/btn_month_2"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_month_2"
android:layout_width="99dp"
android:layout_height="38dp"
android:background="@drawable/button_design_gray_50"
android:text="2월"
android:layout_marginHorizontal="6dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/btn_month_1"
app:layout_constraintRight_toLeftOf="@id/btn_month_3"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_month_3"
android:layout_width="99dp"
android:layout_height="38dp"
android:background="@drawable/button_design_gray_50"
android:text="3월"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/btn_month_2"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_month_group2"
android:layout_width="309dp"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_month_group1">
<Button
android:id="@+id/btn_month_4"
android:layout_width="99dp"
android:layout_height="38dp"
android:background="@drawable/button_design_gray_50"
android:text="4월"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/btn_month_5"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_month_5"
android:layout_width="99dp"
android:layout_height="38dp"
android:background="@drawable/button_design_gray_50"
android:text="5월"
android:layout_marginHorizontal="6dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/btn_month_4"
app:layout_constraintRight_toLeftOf="@id/btn_month_6"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_month_6"
android:layout_width="99dp"
android:layout_height="38dp"
android:background="@drawable/button_design_gray_50"
android:text="6월"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/btn_month_5"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_month_group3"
android:layout_width="309dp"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_month_group2">
<Button
android:id="@+id/btn_month_7"
android:layout_width="99dp"
android:layout_height="38dp"
android:background="@drawable/button_design_gray_50"
android:text="7월"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/btn_month_8"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_month_8"
android:layout_width="99dp"
android:layout_height="38dp"
android:background="@drawable/button_design_gray_50"
android:text="8월"
android:layout_marginHorizontal="6dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/btn_month_7"
app:layout_constraintRight_toLeftOf="@id/btn_month_9"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_month_9"
android:layout_width="99dp"
android:layout_height="38dp"
android:background="@drawable/button_design_gray_50"
android:text="9월"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/btn_month_8"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_month_group4"
android:layout_width="309dp"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_month_group3">
<Button
android:id="@+id/btn_month_10"
android:layout_width="99dp"
android:layout_height="38dp"
android:background="@drawable/button_design_gray_50"
android:text="10월"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/btn_month_11"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_month_11"
android:layout_width="99dp"
android:layout_height="38dp"
android:background="@drawable/button_design_gray_50"
android:text="11월"
android:layout_marginHorizontal="6dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/btn_month_10"
app:layout_constraintRight_toLeftOf="@id/btn_month_12"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_month_12"
android:layout_width="99dp"
android:layout_height="38dp"
android:background="@drawable/button_design_gray_50"
android:text="12월"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/btn_month_11"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
그리고 이건 내가 구현한 캘린더뷰 프래그먼트의 xml코드 중 일부이다.
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_select_date"
android:layout_width="match_parent"
android:layout_height="25dp"
android:layout_marginHorizontal="120dp"
android:layout_marginTop="31dp"
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:id="@+id/fl_select_date"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="36dp"
android:layout_marginBottom="126dp"
android:background="@drawable/layout_select_date_white"
android:elevation="4dp"
android:paddingTop="32dp"
android:paddingBottom="30dp"
android:visibility="gone"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
달력 상단의 클릭 리스너를 구현하기 위해
cl_select_date를 만들어서 달력 상단에 덧붙였고, 내가 만든 메뉴 선택 프래그먼트를 fl_select_date 프레임 레이아웃에 붙였다. (일단 클릭 전엔 안보여야 하므로 visibility속성을 gone으로 주었다.)
package com.kuit.conet.Home
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.kuit.conet.databinding.DialogDateChooseBinding
import java.util.*
class choose_date_dialog : Fragment(){
lateinit var binding : DialogDateChooseBinding
interface OnButtonClickListener {
fun onButtonClicked(year : Int, month : Int)
}
private var buttonClickListener: OnButtonClickListener? = null
fun setOnButtonClickListener(listener: OnButtonClickListener) {
buttonClickListener = listener
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DialogDateChooseBinding.inflate(inflater, container, false)
if(binding.tvYear.text.toString() == ""){
val calendar = Calendar.getInstance()
val year = calendar.get(Calendar.YEAR)
binding.tvYear.text = year.toString()
}
binding.ivPrevYear.setOnClickListener {
var year = binding.tvYear.text.toString().toInt()
year = year - 1
binding.tvYear.text = year.toString()
}
binding.ivNextYear.setOnClickListener {
var year = binding.tvYear.text.toString().toInt()
year = year + 1
binding.tvYear.text = year.toString()
}
binding.btnMonth1.setOnClickListener {
val month = 1
val year = binding.tvYear.text.toString().toInt()
buttonClickListener?.onButtonClicked(year, month)
}
binding.btnMonth2.setOnClickListener {
val month = 2
val year = binding.tvYear.text.toString().toInt()
buttonClickListener?.onButtonClicked(year, month)
}
binding.btnMonth3.setOnClickListener {
val month = 3
val year = binding.tvYear.text.toString().toInt()
buttonClickListener?.onButtonClicked(year, month)
}
binding.btnMonth4.setOnClickListener {
val month = 4
val year = binding.tvYear.text.toString().toInt()
buttonClickListener?.onButtonClicked(year, month)
}
binding.btnMonth5.setOnClickListener {
val month = 5
val year = binding.tvYear.text.toString().toInt()
buttonClickListener?.onButtonClicked(year, month)
}
binding.btnMonth6.setOnClickListener {
val month = 6
val year = binding.tvYear.text.toString().toInt()
buttonClickListener?.onButtonClicked(year, month)
}
binding.btnMonth7.setOnClickListener {
val month = 7
val year = binding.tvYear.text.toString().toInt()
buttonClickListener?.onButtonClicked(year, month)
}
binding.btnMonth8.setOnClickListener {
val month = 8
val year = binding.tvYear.text.toString().toInt()
buttonClickListener?.onButtonClicked(year, month)
}
binding.btnMonth9.setOnClickListener {
val month = 9
val year = binding.tvYear.text.toString().toInt()
buttonClickListener?.onButtonClicked(year, month)
}
binding.btnMonth10.setOnClickListener {
val month = 10
val year = binding.tvYear.text.toString().toInt()
buttonClickListener?.onButtonClicked(year, month)
}
binding.btnMonth11.setOnClickListener {
val month = 11
val year = binding.tvYear.text.toString().toInt()
buttonClickListener?.onButtonClicked(year, month)
}
binding.btnMonth12.setOnClickListener {
val month = 12
val year = binding.tvYear.text.toString().toInt()
buttonClickListener?.onButtonClicked(year, month)
}
return binding.root
}
}
여기는 내가 구현한 날짜선택 메뉴의 프래그먼트 부분이다. 여기서 클릭한 내용이 캘린더뷰 프래그먼트에도 전달이 되어야하므로 클릭리스너를 인터페이스로 구현해 주었다.
fun showDialog(){
binding.flSelectDate.visibility = View.VISIBLE
val chooseDateDialog = choose_date_dialog()
chooseDateDialog.setOnButtonClickListener(object :
choose_date_dialog.OnButtonClickListener {
override fun onButtonClicked(year: Int, month: Int) {
binding.viewCanlendar.setCurrentDate(CalendarDay.from(year, month-1, 1))
binding.viewCanlendar.setSelectedDate(CalendarDay.from(year, month-1, 1))
binding.flSelectDate.visibility = View.GONE
}
})
parentFragmentManager.beginTransaction() // 메뉴 띄워주는 부분
.replace(R.id.fl_select_date, chooseDateDialog)
.commitAllowingStateLoss()
//chooseDateDialog.show(parentFragmentManager, "chooseDateDialog")
}
여기는 캘린더뷰 프래그먼트에 메뉴를 띄워주는 함수이다.
setCurrentDate와 setSelectedDate메소드와 메뉴에서 클릭한 년/월 데이터를 이용해서 해당 날짜로 이동하는 부분이다. '일' 정보까지는 다루지 않아서 해당 년/월 의 1일 자로 이동하도록 설정해주었다.
사실 스터디때 인터페이스 활용하는 걸 배웠었는데 이번 기회에 그것을 내껄로 만드는 좋은 기회가 될 수 있었던 것 같다.