Добро пожаловать в разбор кейсов, как Apple использует элементы UIKit
в своих приложениях. Сегодня разберу Календарь. До этого уже разобрал Калькулятор. Я - Иван Воробей, веду телеграмм канал для iOS Разработчиков «Код Воробья».
Календарь сделали на сценах. Для 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
. Расставлены подсказки.
Управление голосом размечено на каждый час в течение дня. Для событий диктуется заголовок, время, календарь и как можно взаимодействовать с элементом.
На экране года Voice Control
только для месяцев. Voice Over
для года и названия месяцев.
Accessibility
добавлен по всему приложению.