본문 바로가기

안드로이드

[Android / Kotlin ] ViewPager2 로 달력만들기 1편

728x90

 

오늘은 ViewPager2 와 리사이클러뷰를 활용하여서 달력을 만들어보도록 하겠습니다. 

https://developer.android.com/reference/androidx/viewpager2/widget/ViewPager2

 

ViewPager2  |  Android Developers

androidx.car.app.managers

developer.android.com

 

 

CalendarFragment를 생성하겠습니다. 

 

 

fragment_calendar

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
   >

    <TextView
        android:id="@+id/calendar_year_month_text"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="2020년 01월"
        android:textSize="20sp"
        android:textStyle="bold"
        android:textColor="#000000"
        android:gravity="center_vertical|start"
        android:layout_marginStart="15dp"
      />

    <View
        android:id="@+id/div"
        android:layout_width="match_parent"
        android:layout_height="1dp"
      />

    <LinearLayout
        android:id="@+id/calendar_header"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:gravity="center_vertical"
        android:orientation="horizontal">
        <TextView android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_horizontal"
            android:text="SUN"
          />
        <TextView android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_horizontal"
            android:text="MON"
           />
        <TextView android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_horizontal"
            android:text="TUE"
           />
        <TextView android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_horizontal"
            android:text="WED"
           />
        <TextView android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_horizontal"
            android:text="THU"
          />
        <TextView android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_horizontal"
            android:text="FRI"
          />
        <TextView android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_horizontal"
            android:text="SAT"
          />

    </LinearLayout>
    <LinearLayout
        android:id="@+id/calendar_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/calendar_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:spanCount="7"
            android:adjustViewBounds="true"
            app:layout_constrainedHeight="true"
            tools:listitem="@layout/item_calendar_date_list"/>
    </LinearLayout>
</LinearLayout>

 

 

layout안에 recyclerview가 있으니 item도 만들어줘야겠죠 

item을 만들어줍니다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <TextView
        android:id="@+id/item_calendar_date_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="1"
        android:textSize="15sp"
        android:textColor="#000000"
        android:gravity="center_horizontal|top"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

    <View
        android:id="@+id/item_calendar_dot_view"
        android:layout_width="10dp"
        android:layout_height="10dp"
        app:layout_constraintTop_toBottomOf="@id/item_calendar_date_text"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

 

FragmentStateAdapter를 만들어줍니다. 

FragmentStateAdapter는 페이지를 얼만큼만들어줄것인지와 포지션값을 나타내주는 어댑터 역할입니다. 

position 값을 우리가 생성한 CalendarFragmnet에 넣어줘서 생성합니다.

class CalendarPagerFragmentStateAdapter(fragmentActivity: FragmentActivity): FragmentStateAdapter(fragmentActivity) {
    private val pageCount = Int.MAX_VALUE
    val fragmentPosition = Int.MAX_VALUE / 2

    override fun getItemCount(): Int = pageCount
    override fun createFragment(position: Int): Fragment {
        return CalendarFragment(position)
    }
}

 

 

CalendarFragment

class CalendarFragment(index: Int) : BaseFragment<FragmentCalendarBinding>(FragmentCalendarBinding::inflate){

    private var pageIndex = index
    private lateinit var currentDate: Date

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initView(view)
        initCalendar()
    }

    private fun initView(view: View) {
        pageIndex -= (Int.MAX_VALUE / 2)
        val date = Calendar.getInstance().run {
            add(Calendar.MONTH, pageIndex)
            time
        }
        currentDate = date
        val datetime: String = SimpleDateFormat(requireContext().getString(R.string.calendar_year_month_format), Locale.KOREA).format(date.time)
        binding.calendarYearMonthText.text = datetime
    }

    private fun initCalendar() {
        val calendarAdapter = CalendarAdapter(requireContext(), binding.calendarLayout, currentDate)
        binding.calendarView.apply {
            adapter = calendarAdapter
            layoutManager = GridLayoutManager(requireContext(), 7, GridLayoutManager.VERTICAL, false)
            setHasFixedSize(true)
        }

    }

}

 

 

2편에서 계속하겠습니다.