[안드로이드 스튜디오] Fragment로 주간 캘린더 만들기

  • 사진의 현재 날짜는 2020-01-01에 수정하면서 캡쳐해서 글 작성날짜와 다른 것임.

CalendarFragment 만들기

New > Fragment > BlankFragment

  • (Fragment와 xml 파일이 만들어진다)

Fragment에서 binding 사용하기

private var _binding: FragmentCalendarBinding? = null
private val binding get() = _binding!!

  • onCreateView
    _binding = FragmentCalendarBinding.inflate(inflater, container, false)
    val root: View = binding.root
    return root
class CalendarFragment : Fragment() {

    private var _binding: FragmentCalendarBinding? = null
    private val binding get() = _binding!!

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentCalendarBinding.inflate(inflater, container, false)
        val root: View = binding.root

        return root
    }
}

xml UI 형태...? 만들기

  • 현재 연도, 월 :: TextView
  • 주간캘린더뷰 :: RecyclerView
<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context=".ui.calendar.CalendarFragment">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        android:text="2021 - 12"
        android:textAlignment="center"
        android:textStyle="bold" />
    
    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent" />

</LinearLayout>

현재 날짜 불러오기

  • LocalDateTime 사용

    LocalDateTime.now() :: 현재 기본 날짜 및 시간을 가져올 수 있음.
    여기에서 format을 지정해주면 원하는 형태로 날짜나 시간을 각각 가져올 수 있다!


  • 이 뒤부터는 순서가 헷갈려서 완성된 코드만 올림..

item_calendar_list

  • RecyclerView에서 사용될 item 1개의 layout 만들기
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/week_cardview"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:focusable="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/day"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text=""
            android:textAlignment="center" />

        <TextView
            android:id="@+id/date"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="19"
            android:textAlignment="center" />
    </LinearLayout>

</androidx.cardview.widget.CardView>

fragment_calendar

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context=".ui.calendar.CalendarFragment">

    <TextView
        android:id="@+id/text_year_month"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="5dp"
        android:layout_marginBottom="5dp"
        android:text="2021 - 12"
        android:textSize="20dp"
        android:textAlignment="center"
        android:textStyle="bold" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/week_recycler"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent" />

</LinearLayout>

background_blue.xml

  • res > drawble
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="false" android:state_pressed="false">
        <shape>
            <!-- <solid android:color="@android:color/"/> -->
            <!-- 선 굵기 -->
            <stroke android:width="1dp" android:color="#5690FF" />
            <!-- 여기 모서리 둥글게 -->
            <corners android:radius="4dp" />
        </shape>
    </item>
</selector>

CalendarAdapter

class CalendarAdapter(private val cList: List<CalendarVO>) :
    RecyclerView.Adapter<CalendarAdapter.CalendarViewHolder>() {

    class CalendarViewHolder(private val binding: ItemCalendarListBinding) :
        RecyclerView.ViewHolder(binding.root) {
        fun bind(item: CalendarVO) {
            binding.date.text = item.cl_date
            binding.day.text = item.cl_day

            var today = binding.date.text

            // 오늘 날짜
            val now = LocalDate.now().format(DateTimeFormatter.ofPattern("dd").withLocale(Locale.forLanguageTag("ko")))
            // 오늘 날짜와 캘린더의 오늘 날짜가 같을 경우 background_blue 적용하기
            if (today == now) {
                binding.weekCardview.setBackgroundResource(R.drawable.background_blue)
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CalendarViewHolder {
        val binding = ItemCalendarListBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return CalendarViewHolder(binding)
    }

    override fun onBindViewHolder(holder: CalendarViewHolder, position: Int) {
        holder.bind(cList[position])
    }

    override fun getItemCount(): Int {
        return cList.size
    }
    
}

CalendarVO

data class CalendarVO(
    var cl_date: String = "", // 날짜
    var cl_day: String = "" // 요일
)

array.xml

  • res > values
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- Calendar Array -->
    <string-array name="calendar_day">
        <item></item>
        <item></item>
        <item></item>
        <item></item>
        <item></item>
        <item></item>
        <item></item>
    </string-array>
</resources>

CalendarFragment

class CalendarFragment : Fragment() {

    private var _binding: FragmentCalendarBinding? = null
    private val binding get() = _binding!!

    lateinit var calendarAdapter: CalendarAdapter
    private var calendarList = ArrayList<CalendarVO>()

    companion object {
        fun newInstance() = CalendarFragment()
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentCalendarBinding.inflate(inflater, container, false)
        val root: View = binding.root

        return root
    }

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

        var week_day: Array<String> = resources.getStringArray(R.array.calendar_day)

        calendarAdapter = CalendarAdapter(calendarList)

        calendarList.apply {
            val dateFormat = DateTimeFormatter.ofPattern("dd").withLocale(Locale.forLanguageTag("ko"))
            val monthFormat = DateTimeFormatter.ofPattern("yyyy년 MM월").withLocale(Locale.forLanguageTag("ko"))

            val localDate = LocalDateTime.now().format(monthFormat)
            binding.textYearMonth.text = localDate

            var preSunday: LocalDateTime = LocalDateTime.now().with(TemporalAdjusters.previous(DayOfWeek.SUNDAY))

            for (i in 0..6) {
                Log.d("날짜만", week_day[i])

                calendarList.apply {
                    add(CalendarVO(preSunday.plusDays(i.toLong()).format(dateFormat), week_day[i]))
                }
                Log.d("저번 주 일요일 기준으로 시작!", preSunday.plusDays(i.toLong()).format(dateFormat))
            }
        }
        binding.weekRecycler.adapter = calendarAdapter
        binding.weekRecycler.layoutManager = GridLayoutManager(context, 7)
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

}

좋은 웹페이지 즐겨찾기