From ac9a035049b4a17931c5b4ffebe4daad7affdebf Mon Sep 17 00:00:00 2001 From: Malik Khiraev Date: Fri, 26 Jul 2019 20:12:54 +0300 Subject: [PATCH 1/5] Create README.md --- recyclerview-calendar/README.md | 201 ++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 recyclerview-calendar/README.md diff --git a/recyclerview-calendar/README.md b/recyclerview-calendar/README.md new file mode 100644 index 00000000..105d4e82 --- /dev/null +++ b/recyclerview-calendar/README.md @@ -0,0 +1,201 @@ +recyclerview-calendar +==== + +Модуль с календарем. + +### Основные интерфейсы и классы + +Класс `CalendarRecyclerView` - класс, который наследуется от `RecyclerView` и позволяет работать с `CalendarAdapter`. + +Абстрактный класс `CalendarAdapter` наследуется от `RecyclerView.Adapter`. Имеет три параметра: +* `TDayViewHolder` - вьюхолдер с датой, +* `THeaderViewHolder` - вьюхолдер с заголовком - названием месяца, +* `TEmptyViewHolder` - вьюхолдер для пустых ячеек. + +В конструкторе принимает *startDate* - дата начала календаря, *endTime* - дата конца календаря и *vararg* названий месяцев. Первые два параметра имеют тип `DateTime`. + +Методы: + +* *updateCalendarItems* - обновить календарь, принимает два `DateTime`: начало и конец календаря. + +* *setSelectedRange* - отметить непрерывный диапазон дат, принимает начало и конец диапазона в виде объектов `DateTime`. + +* *getPositionToScroll* - получить позицию к которой происходит скролл при открытии календаря. + +* *getCalendarItems* - полуить список ячеек(`CalendarItem`) календаря. + +* *getMonthsNameByHeaderCalendarItem* - получить название месяца для переданного `CalendarHeaderItem`. + +При релизации данного класса, необходимо реализовать следующие методы: + +* *createHeaderViewHolder* - создание `ViewHolder` для заголовка месяца. + +* *createEmptyViewHolder* - создание `ViewHolder` для пустой ячейки. + +* *createDayViewHolder* - создание `ViewHolder` для ячейки с числом. + +* *bindHeaderItem* - прикрепление информации о месяце и годе к строке-названию месяца. + +* *bindEmptyItem* - прикрепление информации о состоянии выбора к пустой ячейке. + +* *bindDayItem* - прикрепление информации о дне ко `ViewHolder`. + + +У класса `CalendarAdapter` есть вложенный класс-перечисление `SelectionMode` для отметки ячейки при выборе диапазона. У данного перечисления может быть 5 значений: +* `SELECTED_FIRST`, +* `SELECTED_MIDDLE`, +* `SELECTED_LAST`, +* `SELECTED_ONE_ONLY`, +* `NOT_SELECTED` + +Интерфейс `CalendarItem` описывает элемент календаря. Имеет два метода *getStartRange* - получить начало календаря и *getEndRange* - получить конец календаря. + +Реализации данного интерфейса: `CalendarDayItem`, `CalendarEmptyItem` и `CalendarHeaderItem`. + +Класс `CalendarDayItem` - описывает один сплошной диапазон с датами. У него есть поле *positionOfFirstDate* - это число, с которого начинается данный диапазон, *dateOfFirstDay* - дата первого дня диапазона в миллисекундах и *comparingToToday* - отношение диапазона к сегодняшнему дню. Для "сегодня" используется отдельный элемент *startRange* и *endRange* которого равны. + +Класс `CalendarEmptyItem` - описывает диапазон пустых ячеек. + +Класс `CalendarHeaderItem` - описывает заголовок месяца. Имеет информацию о годе и месяце. + +Класс `CalendarUtils` содержит методы для работы с `CalendarItem`: + +* *findItemByPosition* - найти элемент по его позиции. Принимает список `CalendarItem` и позицию. + +* *findPositionOfSelectedMonth* - найти позицию элемента-заголовка месяца, в которому относится переданная позиция. Принимает список `CalendarItem` и позицию. + +* *findPositionByDate* - найти позицицию переданной даты. Принимает список `CalendarItem` и дату в миллисекундах. + +* *fillRange* - заполнить заданный диапазон и получить список `CalendarItem`. Принимает *startDate* и *endDate* в виде объектов `DateTime`. + +### Примеры + +В примере используется `ViewController` из модуля [navigation](https://github.com/TouchInstinct/RoboSwag/tree/master/navigation) + +Файл `CalendarDataImpl.kt` - реализация `CalendarAdapter` + +```Kotlin +class CalendarAdapterImpl( + startDay: DateTime, + endDate: DateTime +) : CalendarAdapter(startDay, endDate, *months) { + + companion object { + val months = arrayOf("Январь", "Февраль" /* and others */) + } + + private var onDateClickedListener: ((DateTime) -> Unit)? = null + + override fun createHeaderViewHolder(parent: ViewGroup): CalendarHeaderViewHolder = + CalendarHeaderViewHolder(UiUtils.inflate(R.layout.item_calendar_header_view, parent)) + + override fun createEmptyViewHolder(parent: ViewGroup): CalendarEmptyViewHolder = + CalendarEmptyViewHolder(UiUtils.inflate(R.layout.item_calendar_empty_view, parent)) + + override fun createDayViewHolder(parent: ViewGroup): CalendarDayViewHolder = + CalendarDayViewHolder(UiUtils.inflate(R.layout.item_calendar_day_view, parent)) + + override fun bindHeaderItem( + viewHolder: CalendarHeaderViewHolder, + year: Int, + monthName: String, + firstMonth: Boolean + ) { + viewHolder.bind("$monthName $year") + } + + override fun bindEmptyItem(viewHolder: CalendarEmptyViewHolder, selectionMode: SelectionMode) { + viewHolder.bind(selectionMode) + } + + override fun bindDayItem( + viewHolder: CalendarDayViewHolder, + day: String, + date: DateTime, + selectionMode: SelectionMode, + dateState: ComparingToToday + ) { + viewHolder.bind(day, date, selectionMode, dateState, onDateClickedListener) + } + + fun setOnDateClickedListener(onDateClickedListener: (DateTime) -> Unit) { + this.onDateClickedListener = onDateClickedListener + notifyDataSetChanged() + } + +} + +``` + +Файл `PeriodsViewController.kt` + +```Kotlin +class PeriodsViewController( + creationContext: CreationContext +) : ViewController( + creationContext, + R.layout.view_controller_period +) { + + private val calendarRecyclerView: CalendarRecyclerView = + findViewById(R.id.view_controller_period_calendar) + + init { + val startPeriod = DateTime().withYear(2018).withDayOfYear(1) + val endPeriod = DateTime.now().plusMonths(1).dayOfMonth().withMaximumValue() + + val calendarAdapter = CalendarAdapterImpl(startPeriod, endPeriod) + + calendarAdapter.setOnDateClickedListener { dateTime -> + + // Do something + + } + calendarRecyclerView.setAdapter(calendarAdapter) + } + +} +``` + +Файл `view_controller_period.xml` +```xml + + + + + + + + +``` +### Зависимости + +Для работы с данным модулем необходимо так же подключить модуль [logging](https://github.com/TouchInstinct/RoboSwag/tree/master/logging). + +```gradle +implementation project(':logging') +``` + +### Подключение + +```gradle +implementation project(':recyclerview-calendar') +``` From 7fd379992ab821c3e54e4d80cabaa790b45c64a4 Mon Sep 17 00:00:00 2001 From: Malik Khiraev Date: Mon, 9 Sep 2019 18:46:24 +0300 Subject: [PATCH 2/5] Fix "about" --- recyclerview-calendar/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recyclerview-calendar/README.md b/recyclerview-calendar/README.md index 105d4e82..fa024709 100644 --- a/recyclerview-calendar/README.md +++ b/recyclerview-calendar/README.md @@ -1,7 +1,7 @@ recyclerview-calendar ==== -Модуль с календарем. +Календарь с гибкими настройками внешнего вида заголовка, ячеек. Позволяет выделять заданный промежуток времени. ### Основные интерфейсы и классы From d593251d456bde05aeed8ab8de81e580b0f4607b Mon Sep 17 00:00:00 2001 From: Malik Khiraev Date: Mon, 9 Sep 2019 18:48:10 +0300 Subject: [PATCH 3/5] Fix a sentence --- recyclerview-calendar/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recyclerview-calendar/README.md b/recyclerview-calendar/README.md index fa024709..ede05948 100644 --- a/recyclerview-calendar/README.md +++ b/recyclerview-calendar/README.md @@ -1,7 +1,7 @@ recyclerview-calendar ==== -Календарь с гибкими настройками внешнего вида заголовка, ячеек. Позволяет выделять заданный промежуток времени. +Календарь с гибкими настройками внешнего вида заголовка и ячеек. Позволяет выделять заданный промежуток времени. ### Основные интерфейсы и классы From 6ee193d5b4d416942487a04df6a9bb2879705a8a Mon Sep 17 00:00:00 2001 From: Malik Khiraev Date: Tue, 10 Sep 2019 14:10:01 +0300 Subject: [PATCH 4/5] Update README.md --- recyclerview-calendar/README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/recyclerview-calendar/README.md b/recyclerview-calendar/README.md index ede05948..a121b114 100644 --- a/recyclerview-calendar/README.md +++ b/recyclerview-calendar/README.md @@ -193,9 +193,3 @@ class PeriodsViewController( ```gradle implementation project(':logging') ``` - -### Подключение - -```gradle -implementation project(':recyclerview-calendar') -``` From 0c0ddeb37fb8be37b13d7e1ee6945c2706683e1f Mon Sep 17 00:00:00 2001 From: Malik Khiraev Date: Tue, 10 Sep 2019 14:13:20 +0300 Subject: [PATCH 5/5] Update README.md --- recyclerview-calendar/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/recyclerview-calendar/README.md b/recyclerview-calendar/README.md index a121b114..1a00b5a9 100644 --- a/recyclerview-calendar/README.md +++ b/recyclerview-calendar/README.md @@ -1,7 +1,7 @@ recyclerview-calendar ==== -Календарь с гибкими настройками внешнего вида заголовка и ячеек. Позволяет выделять заданный промежуток времени. +Календарь с гибкими настройками внешнего вида заголовка и ячеек. Позволяет выделять и работать с заданным промежутком времени. ### Основные интерфейсы и классы