본문 바로가기

Kotlin_study

[Kotlin] CosmoCalendar library 사용하기

## 다이어리 프로젝트 with SandBurger

종강과 함께 잠시 쉬고있던 프로젝트를 다시 시작했습니다.

프로젝트의 핵심 기능을 구현하기 위해 달력 커스텀이 필요하여 cosmocalendar 라이브러리를 사용하여 구현하였습니다.

 

동작과정은 아래와 같습니다

 

 

 

일정 추가 화면

일정 추가 화면입니다. 여기서 시작일, 종료일 클릭 시 각각 하단에 calendar가 보이며 날짜를 선택할 수 있고, timePicker를 사용하여 시간 선택을 하게 했습니다.

 

fragment_add_schedule.xml

<?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="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <ImageView
        android:id="@+id/add_schedule_top_iv"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:src="@color/brand_light"
        android:layout_marginBottom="17dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toTopOf="@id/add_schedule_write_diary_et"/>
    <ImageButton
        android:id="@+id/add_schedule_exit_ib"
        android:layout_width="15dp"
        android:layout_height="12dp"
        android:src="@drawable/ic_left_arrow"
        android:scaleType="fitCenter"
        android:background="@color/white"
        android:layout_marginStart="17dp"
        app:layout_constraintTop_toTopOf="@id/add_schedule_date_tv"
        app:layout_constraintBottom_toBottomOf="@id/add_schedule_date_tv"
        app:layout_constraintStart_toStartOf="parent"/>
    <TextView
        android:id="@+id/add_schedule_date_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:text="@string/add_schedule"
        android:textColor="@color/background_white"
        android:layout_marginTop="33dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="저장"
        android:textSize="14sp"
        android:layout_marginEnd="21dp"
        app:layout_constraintTop_toTopOf="@id/add_schedule_date_tv"
        app:layout_constraintBottom_toBottomOf="@id/add_schedule_date_tv"
        app:layout_constraintEnd_toEndOf="parent"/>

    <EditText
        android:id="@+id/add_schedule_write_diary_et"
        android:layout_width="match_parent"
        android:layout_height="32dp"
        android:hint="일정을 입력하세요."
        android:textSize="16sp"
        android:inputType="text"
        android:background="@color/white"
        android:layout_marginHorizontal="19dp"
        android:layout_marginTop="99dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
    <ImageView
        android:id="@+id/add_schedule_divider_iv"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:src="@drawable/gray_line"
        android:layout_marginTop="24dp"
        android:layout_marginHorizontal="16dp"
        app:layout_constraintTop_toBottomOf="@id/add_schedule_write_diary_et"
        app:layout_constraintStart_toStartOf="parent"/>
    <ImageView
        android:id="@+id/add_schedule_clock_iv"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_marginTop="16dp"
        android:layout_marginStart="16dp"
        app:layout_constraintTop_toBottomOf="@id/add_schedule_divider_iv"
        app:layout_constraintStart_toStartOf="parent"/>
    <TextView
        android:id="@+id/add_schedule_all_day_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="하루종일"
        android:textColor="@color/font_black"
        android:layout_marginStart="16sp"
        android:textSize="16sp"
        app:layout_constraintTop_toTopOf="@id/add_schedule_clock_iv"
        app:layout_constraintStart_toEndOf="@id/add_schedule_clock_iv"/>
    <Switch
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="7dp"
        app:layout_constraintTop_toTopOf="@id/add_schedule_clock_iv"
        app:layout_constraintEnd_toEndOf="parent"/>
    <TextView
        android:id="@+id/add_schedule_start_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:text="시작일"
        android:textColor="@color/font_black"
        android:layout_marginTop="32dp"
        app:layout_constraintTop_toBottomOf="@id/add_schedule_all_day_tv"
        app:layout_constraintStart_toStartOf="@id/add_schedule_all_day_tv"/>
    <TextView
        android:id="@+id/add_schedule_start_day_tv"
        android:layout_width="120dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="44dp"
        android:gravity="center"
        android:text="2022.05.03(화)"
        android:textSize="14dp"
        android:textColor="@color/font_black"
        app:layout_constraintTop_toTopOf="@id/add_schedule_start_tv"
        app:layout_constraintStart_toEndOf="@id/add_schedule_start_tv"/>
    <TextView
        android:id="@+id/add_schedule_start_time_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="14sp"
        android:textColor="@color/font_black"
        android:text="오전 06:00"
        android:layout_marginEnd="16dp"
        app:layout_constraintTop_toTopOf="@id/add_schedule_start_day_tv"
        app:layout_constraintEnd_toEndOf="parent"/>
    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/add_schedule_start_lo"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintTop_toBottomOf="@id/add_schedule_start_day_tv"
        app:layout_constraintStart_toStartOf="parent">
        <TimePicker
            android:id="@+id/add_schedule_start_time_picker_tp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:timePickerMode="spinner"
            android:visibility="gone"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"/>
        <com.applikeysolutions.cosmocalendar.view.CalendarView
            android:id="@+id/add_schedule_start_calendar_cv"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:visibility="gone"
            app:firstDayOfTheWeek="sunday"
            app:orientation="horizontal"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"/>
    </androidx.constraintlayout.widget.ConstraintLayout>

    <TextView
        android:id="@+id/add_schedule_end_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:text="종료일"
        android:textColor="@color/font_black"
        android:layout_marginTop="32dp"
        app:layout_constraintTop_toBottomOf="@id/add_schedule_start_lo"
        app:layout_constraintStart_toStartOf="@id/add_schedule_start_tv"/>
    <TextView
        android:id="@+id/add_schedule_end_day_tv"
        android:layout_width="120dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="44dp"
        android:gravity="center"
        android:text="2022.05.03(화)"
        android:textSize="14dp"
        android:textColor="@color/font_black"
        app:layout_constraintTop_toTopOf="@id/add_schedule_end_tv"
        app:layout_constraintStart_toEndOf="@id/add_schedule_end_tv"/>
    <TextView
        android:id="@+id/add_schedule_end_time_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="14sp"
        android:textColor="@color/font_black"
        android:text="오전 06:00"
        android:layout_marginEnd="16dp"
        app:layout_constraintTop_toTopOf="@id/add_schedule_end_day_tv"
        app:layout_constraintEnd_toEndOf="parent"/>
    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/add_schedule_end_lo"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintTop_toBottomOf="@id/add_schedule_end_day_tv"
        app:layout_constraintStart_toStartOf="parent">
        <com.applikeysolutions.cosmocalendar.view.CalendarView
            android:id="@+id/add_schedule_end_calendar_cv"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:visibility="gone"
            app:firstDayOfTheWeek="sunday"
            app:orientation="horizontal"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"/>
        <TimePicker
            android:id="@+id/add_schedule_end_time_picker_tp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:timePickerMode="spinner"
            android:visibility="gone"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
    <ImageView
        android:id="@+id/add_schedule_divider2_iv"
        android:layout_width="match_parent"
        android:layout_height="15dp"
        android:background="@color/background_white"
        android:layout_marginTop="15dp"
        app:layout_constraintTop_toBottomOf="@id/add_schedule_end_lo"
        app:layout_constraintStart_toStartOf="parent"/>
    <TextView
        android:id="@+id/add_schedule_alarm_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="알림"
        android:textSize="16sp"
        android:textColor="@color/font_black"
        android:layout_marginTop="15dp"
        app:layout_constraintTop_toBottomOf="@id/add_schedule_divider2_iv"
        app:layout_constraintStart_toStartOf="@id/add_schedule_all_day_tv"/>
    <ImageView
        android:id="@+id/add_schedule_divider3_iv"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:src="@drawable/gray_line"
        android:layout_marginTop="15dp"
        android:layout_marginHorizontal="16dp"
        app:layout_constraintTop_toBottomOf="@id/add_schedule_alarm_tv"
        app:layout_constraintStart_toStartOf="parent"/>
    <TextView
        android:id="@+id/add_schedule_memo_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="메모"
        android:textSize="16sp"
        android:textColor="@color/font_black"
        android:layout_marginTop="15dp"
        app:layout_constraintTop_toBottomOf="@id/add_schedule_divider3_iv"
        app:layout_constraintStart_toStartOf="@id/add_schedule_all_day_tv"/>
</androidx.constraintlayout.widget.ConstraintLayout>

 

AddScheduleFragment.kt

원하는 날짜를 선택하고 이를 원하는 방식으로 처리하기 위해서는 calendarview.selectedDays를 통해 선택한 날짜를 가져와서 필요한 데이터를 이용하여 처리해야합니다. 제 경우에는 이 부분에서 년, 월, 일, 요일을 원하는 방식으로 표현하기 위해 위와 같은 함수를 만들어 사용했습니다.

 

위에서 날짜를 처리한 것과 마찬가지로 timepicker를 통해 얻은 시간을 처리하기 위해, 24시간으로 표현되는 시간을 처리해주는 함수를 만들어 사용했습니다.

 

focusChangeListener를 사용하여 구현하려고 했으나, CalendarView에서 focus가 변경될 때 동작하지 않아서 러프하게 구현하게 되었습니다. 이 부분은 추후에 다시 확인해보려고 합니다.

 

CalendarView 또는 TimePicker를 선택했을 때, 기존에 이미 VISIBLE인, 해당하는 text를 선택한 날짜, 시간으로 변경해주게끔 했습니다. 그리고 선택할 때 text의 color를 푸른색으로 변경해줬으므로, 검은색르로 다시 변경해줍니다.

 

changeText함수를 사용하여 text를 갱신하고 view의 visibility를 view의 현재 visibility에 따라 변경해주었습니다.

 

참고

ApplikeySolutions/CosmoCalendar: 📅 CosmoCalendar is a fully customizable calendar with a wide variety of features and displaying modes. (github.com)