Как устроен Календарь

Новое событие сделали двухслойной картинкой. Auto Layout и фреймы.

Читается за 2 минуты Обновлено 15 дней назад

Сделали на сценах. Для iPhone root-сцена называется MobileCalWindow.

Экран дня

Контейнер UINavigationController. Навигацию между страницами-днями сделали на UIScrollView, класс назвали BlockableScrollView. У скрола включен пейджинг.

В памяти хранят вчерашений, сегодняшний и завтрашний день. В Календаре используют кастомную систему переиспользования, что-то похожее на UICollectionView, но управляется вручную. Скорее всего, это сделано для оптимизации в прошлом и до нашего времени сохранился легаси-код.

Превью события в приложении Календарь.

Ячейки событий сделали двухслойными картинками. Первый слой - фоновая картинка, второй слой - текст внутри события. Залитая линия справа события это часть фоновой картинки. У события две точки для изменения времени - слева внизу и справа вверху. Им расширили размеры, но фон - прозрачный. Лейаут ячеек на констрейнтах.

UINavigationBar базовый, справа добавили Stack View для кнопок. Панель с датами назвали PaletteView. Это UIScrollView и она не является частью UINavigationBar. Всю панель поместили над контентом, но под баром и присоединили к нижней точке бара. Фон повторили, чтобы скрыть переход.

 Хедер экрана событий.
Хедер экрана событий.

Разметка времени слева сделана на одном слое, текст отрисовали внутри CALayer. Время разместили слева экрана, события сместились вправо.

 Как устроена разметка времени.
Как устроена разметка времени.

Разметка времени лежит внутри UIVisualEffectView, но визуально применений не нашёл.

Как писал выше, событие - это картинка. Чтобы обрабатывать нажатие на картинку, нужно добавить UITapGestureRecognizer. Так инженеры эпл и сделали - для вью каждого дня добавили тап-жест. В вот жест драга добавлен один на весь экран, а не отдельные жесты для каждого события.

Новое событие

Экран презентуется как модальный контроллер. Сделан на UITableViewController, вью таблицы назвали EKCalendarItemEditorTableView.

 Экран с новое событием.
Экран с новое событием.

Ячейки назвали EKUITableViewCell. Disclosure Indicator справа тоже системные. Ничего уникального в экране не нашёл.

Экран по месяцам

Главная вью UIScrollView. При переходе на экран по месяцам, панель с числами PaletteView съезжает вверх. Она остается в памяти, но не видна на экране телефона.

А вот панель с днями недели визуально остается на месте, но на самом деле это копия. Оригинальная панель уезжает наверх вместе с PaletteView.

 Экран по месяцам
Экран по месяцам

Названия месяцев сделаны на UILabel. Месяц разбивается на горизонтальные недели. Контейнер назвали CompactMonthWeekView.

 Недели в экране по месяцам
Недели в экране по месяцам

Внутри дни недели сделаны через CALayer. Только для текущего дня, который красный кружок, дата это UILabel с красным фоном. Назвали CompactMonthWeekTodayCircle. Лейаут на фреймах.

Сепаратор между неделями это UIView с фоном и высотой 0.333.

Превью дня

Всплывающая панель это таблица. Ячейки назвали EKUIOccurrenceTableViewCell. Лейаут на констрейнтах. Практически все расстояния между элементами выставили фиксированным значением. Отступ от краев ячейки тоже.

 Превью дня для экрана по месяцам.
Превью дня для экрана по месяцам.

Контент ячеек сделан на UILabel. Цветная полоска слева это UIView с фоном.

Экран Год

Надписи годов сделали через UILabel. Контейнер для хедера назвали CompactYearViewYearHeader. Месяцы группируются по 3 в линию. Даты внутри месяца и название отрисовали слоем внутри вью, назвали CompactYearMonthView.

 Экран Год.
Экран Год.

Сделано на UIScrollView с кастомной системой переиспользования.

Список календарей

Сделали таблицей. Ячейки называются EKCalendarChooserCell. Круглые чекмарки слева сделали картинками. Нативный экран без кастомизации.

 Список календарей.
Список календарей.

Accessibility

Все интерактивные элементы поддерживают Voice Over и Voice Control. Расставлены подсказки.

 Разметка Accessibility для дня.
Разметка Accessibility для дня.

Управление голосом размечено на каждый час в течение дня. Для событий диктуется заголовок, время, календарь и как можно взаимодействовать с элементом.

На экране года Voice Control только для месяцев. Voice Over для года и названия месяцев.

 Разметка Accessibility для превью года.
Разметка Accessibility для превью года.

Accessibility добавлен по всему приложению.