[필요 기능!]
원하는 년도와 달을 선택해서 해당 데이터를 불러오는 기능
위의 영상처럼 해당 년도의 달을 선택하면 그 달의 일자를 불러오고, 일자별 task List를 표시하는 기능을 개발 중이었다.
버튼을 클릭하면 연도와 달을 선택하는 coustom dialog view가 필요했다.
<month_picker.xml>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/item_height_double_big"
android:layout_height="@dimen/item_height_double_big"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/round_border">
<LinearLayout
android:gravity="center"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/month_picker_bottom"
android:layout_width="@dimen/item_height_big_180"
android:layout_height="@dimen/item_height_big_150">
<NumberPicker
android:id="@+id/year_picker"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<NumberPicker
android:id="@+id/month_picker"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>
<LinearLayout
android:id="@+id/month_picker_bottom"
android:layout_marginBottom="@dimen/main_margin"
android:padding="@dimen/main_margin"
app:layout_constraintBottom_toBottomOf="parent"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="@dimen/item_height">
<Button
android:id="@+id/btn_cancel"
android:layout_marginEnd="@dimen/main_margin"
android:text ="Cancel"
android:backgroundTint="@color/color_type2"
android:src="@drawable/round_border"
android:padding="@dimen/main_margin"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="@dimen/item_height"/>
<Button
android:id="@+id/btn_set"
android:text ="Set"
android:backgroundTint="@color/color_type2"
android:src="@drawable/round_border"
android:padding="@dimen/main_margin"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="@dimen/item_height"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
아래와 같은 view를 그려준다.
NumberPicker를 사용하였는데 설정된 범위에서 원하는 값을 선택할 수 있으며, 초기값도 지정할 수 있다.
현재 년도와 달을 초기값으로 설정하고, 선택된 값을 데이터로 전달한다.
dialog를 띄어주기 위한 클래스를 선언한다.
class MonthPickerDialog(
private val year:Int,
private val month:Int,
) :DialogFragment() {
DialogFragment를 상속해서 month_picker view에 대한 데이터를 지정한다.
var btnSet: Button? = null
var btnCancel: Button? = null
var monthPicker: NumberPicker? = null
var yearPicker : NumberPicker? = null
위에서 만들어준 xml의 데이터들을 선언해준다.
차례대로 ok버튼, 취소 버튼, 월 선택 number picker, 년도 선택 number picker이다.
onCreateDialog를 통해 activity 내부에서 dialog를 생성한다.
해당 함수를 override 해준다.
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog
builder와 inflater를 선언한다.
bulider를 통해서 view를 그려주고, inflater를 통해서 view의 데이터에 접근할 수 있다.
val builder = AlertDialog.Builder(activity)
val inflater = requireActivity().layoutInflater
inflater를 통해서 dialog view를 선언하고, 위의 변수들을 초기화한다.
val dialog : View = inflater.inflate(R.layout.month_picker,null).also {
btnSet = it.findViewById<Button>(R.id.btn_set)
btnCancel = it.findViewById<Button>(R.id.btn_cancel)
monthPicker = it.findViewById<View>(R.id.month_picker) as NumberPicker
yearPicker = it.findViewById<View>(R.id.year_picker) as NumberPicker
}
이제 각 view에 대한 값이나 클릭 이벤트를 설정한다.
btnSet?.setOnClickListener{
onClickedListener.onClicked(yearPicker!!.value,monthPicker!!.value)
dismiss()
}
btnCancel?.setOnClickListener{
dismiss()
}
monthPicker?.apply {
minValue = 1
maxValue = 12
value = month
}
yearPicker?.apply {
minValue = 2010
maxValue = 2099
value = year
}
numberPicker에서는 minValue, maxValue, value를 설정해주었는데 최솟값, 최댓값, 기본값을 설정한다
기본값으로는 클래스가 선언될 때 전달받은 년도와 달로 설정해준다.
값 세팅이 완료되었으면 builder를 통해서 view를 띄어준다.
builder.setView(dialog)
return builder.create()
set 버튼이 클릭되었을 경우 onClickedListener를 발생하도록 했다.
interface ButtonClickListener {
fun onClicked(year:Int,month:Int)
}
private lateinit var onClickedListener: ButtonClickListener
fun setOnClickedListener(listener: ButtonClickListener) {
onClickedListener = listener
}
위와 같이 interface를 선언하고 버튼이 클릭 되었을 때의 이벤트를 설정한다.
이제 fragment나 activity에서 view를 띄어주는 코드를 작성한다.
dig 클래스를 선언하고 show()를 해당 클래스를 보여준다.
fragment에서 show()를 사용하기 위해서는 두 가지 인자가 필요하다.
1. fragment manger
fragment manager는 mainActivity에서 supportFragmentManager를 받아온다.
private lateinit var fm : FragmentManager
onAttach에서 초기화해주었다.
override fun onAttach(context: Context) {
super.onAttach(context)
mainActivity = context as MainActivity
fm = (activity as MainActivity).supportFragmentManager
}
2. tag
tag는 고유번호 같은 것인데 필요하지 않다면 null을 넣어준다.
binding.taskListCalendar.setOnClickListener {
val dig = MonthPickerDialog(mainActivity.viewModel.currentYear.value!!,mainActivity.viewModel.currentMonth.value!!)
dig.show(fm,null)
dig.setOnClickedListener(object : MonthPickerDialog.ButtonClickListener{
override fun onClicked(year: Int, month: Int) {
changeCalendar(year,month)
}
})
}
이제 원하는 dialog를 얻을 수 있다.
set 버튼에 대한 클릭 이벤트가 발생할 경우 새로운 year, month 값을 받아와서 changeCalendar함수를 실행한다.
private fun changeCalendar(year:Int, month:Int){
mainActivity.viewModel.apply {
initCurrentData(getDate(year,month))
binding.taskListCalendar.text = this.dateTime
}
initRecyclerView()
initAni()
}
changeCalendar 함수는 viewModel에서 현재 달에 대한 정보를 갱신해준다.
데이터가 새로 갱신되었으니 recyclerview를 새로 그려주고, 애니메이션을 적용했다.