1 njnu8jmjtx7znfghp5xyla 1160x620 - Поддержка Dynamic Type в приложении Airbnb

Обзор процесса, советы и подводные камни, которые мы узнали при внедрении Dynamic Type в Airbnb.

Предпосылки

Начиная с iOS 7, Dynamic Type позволяет пользователям выбирать предпочтительный размер шрифта для своего телефона. В Airbnb мы пытаемся создать приложение, которое может использовать все наше сообщество – поскольку Dynamic Type является критически важной функцией доступности, мы знали, что его поддержка позволит эффективно использовать наше приложение. Чтобы проверить важность этой функции, мы проверили данные и увидели, что 30% людей, использующих наше приложение, имели предпочтительный размер шрифта, который не был установлен по умолчанию. Это использование не склоняется к определенным размерам, но равномерно распределяется между большими и меньшими значениями по умолчанию.

Оказывается, поддержка этих предпочтений создает единообразный опыт в ОС, который пользователи замечают. Эксперименты с Dynamic Type по отдельным функциям в приложении Airbnb привели к значительному увеличению вовлеченности, что помогло нам изменить итоговые показатели. Если вы потратите время на поддержку Dynamic Type в своем приложении, пользователи наверняка будут вам благодарны!

Поддержка Dynamic Type в приложении Airbnb
Выбор размера шрифта в iOS

Почему это так важно?

Выходя за рамки метрик, поддержка Dynamic Type обеспечивает более высокий уровень качества компонентов пользовательского интерфейса. Компоновка должна быть достаточно надежной, чтобы обрабатывать широкий спектр предпочтений, аналогично вариациям, создаваемым локализацией и размером экрана устройства. Поскольку большая часть времени при разработке тратится на отдельные устройства и языки, ошибки, воспроизводимые только в определенных конфигурациях, будут слишком часто проскальзывать. К счастью, многие из них сейчас обнаруживаются при тестировании Dynamic Type. Если ваше приложение уже поддерживает изменяющиеся размеры экрана с помощью UITraitCollection и переводов со строками различной длины, есть большая вероятность того, что вы проделали большую часть работы по поддержке Dynamic Type.

Дизайн

Большинство ошибок, с которыми мы сталкивались, когда использовались шрифты большого размера, были связаны с текстом, не соответствующим их контейнерам. Чтобы разрешить эти проблемы, мы создали несколько рекомендаций по дизайну. Во-первых, ширина и высота стали гибкими, что позволяет тексту расширяться до нескольких строк. Во многих случаях это уже должно было быть сделано, поскольку в некоторых языках слова могут быть намного длиннее английских, которые мы используем в макетах дизайна.

Поддержка Dynamic Type в приложении Airbnb

Во-вторых, мы должны были убедиться, что шрифты масштабируются правильно. Это делается путем присвоения каждому тексту соответствующего UIFont.TextStyle. Использование большего TextStyle указывает на то, что ваш шрифт уже большой, поэтому вам больше не нужно увеличивать его.

В-третьих, мы должны были исправить некоторые метки, которые меняли размер. Мы рекомендуем масштабировать всю часть прокручиваемой области на экране, а все остальное следует оставлять статичным. Однако любому, у кого включен большой Dynamic Type, по-прежнему нужен способ просмотра текста в небольших контейнерах, таких как панели вкладок. Если вы используете все стандартные элементы UIKit, это обрабатывается Large Content Viewer:

Поддержка Dynamic Type в приложении Airbnb

Мы подали в Apple отчет об ошибке, запросив новый API для представления всплывающих окон. С тех пор эта возможность была включена в бета-версию iOS 13, поэтому вы скоро сможете увидеть ее в приложении Airbnb.

Разработка

iOS предоставляет в основном автоматические API-интерфейсы Dynamic Type для системных шрифтов, но приложение Airbnb использует пользовательскую гарнитуру Cereal. Для поддержки Dynamic Type мы используем UIFontMetrics. Он обрабатывает масштабирование размера шрифта, высоты строки и отслеживания. Каждый из этих атрибутов существует в двух формах:

  1. Немасштабируемые единицы измерения, которые отображаются пользователям с размером шрифта по умолчанию и являются значениями, которые мы устанавливаем при создании атрибутов шрифта.
  2. Масштабируемые единицы, которые соответствуют preferredContentSizeCategory являются тем, что мы считываем во время выполнения.

Внутри функции будут запрашивать шрифт, используя атрибуты, выраженные в немасштабируемых единицах, и получат объект, содержащий различные функции, которые мы используем для отображения текста, который всегда возвращает значения в масштабированных единицах. Это гарантирует, что любые вычисления, такие как ограничивающая рамка текста, будут использовать масштабированные единицы. Некоторые из наиболее распространенных ошибок, с которыми мы встречались, были вызваны использованием немасштабируемых единиц для вычисления макета вместо масштабированных единиц.

Есть два способа использовать UIFontMetrics для преобразования из немасштабируемых в масштабированные единицы.

Метод #1:

func scaledFont(for font: UIFont, compatibleWith traitCollection: UITraitCollection?) -> UIFont 

Метод #2:

func scaledValue(for value: CGFloat, compatibleWith traitCollection: UITraitCollection?) -> CGFloat 

В этих подходах есть тонкие различия. Рассмотрим следующие примеры, каждый из которых использует свой метод UIFontMetrics:

let traitCollection = UITraitCollection(
  traitsFrom: [self.traitCollection, UITraitCollection(preferredContentSizeCategory: .extraLarge)])
let font = UIFont.systemFont(ofSize: 20)
let metrics = UIFontMetrics(forTextStyle: .body)

// METHOD #1
let scaledFont = metrics.scaledFont(for: font, compatibleWith: traitCollection)
let scaledPointSize = scaledFont.pointSize
let scaledLineHeight = scaledFont.lineHeight

// METHOD #2
let scaledPointSizeFloat = metrics.scaledValue(for: font.pointSize, compatibleWith: traitCollection)
let scaledLineHeightFloat = metrics.scaledValue(for: font.lineHeight, compatibleWith: traitCollection)

В зависимости от устройства, на котором вы работаете, мы наблюдаем такие результаты:

Поддержка Dynamic Type в приложении Airbnb

Результаты не совсем ясны, но, поскольку мы настраиваем высоту строки с помощью NSParagraphStyle, нам нужно использовать функцию масштабирования CGFloat. UIFont с немасштабированным размером точки масштабируется напрямую, чтобы получить настроенный UIFont. Вот полный пример масштабирования NSAttributedString:

let traitCollection = UITraitCollection(
  traitsFrom: [self.traitCollection, UITraitCollection(preferredContentSizeCategory: .extraLarge)])
let fontSize: CGFloat = 20
let lineHeight: CGFloat = 25
let font = UIFont.systemFont(ofSize: fontSize)
let metrics = UIFontMetrics(forTextStyle: .body)

let scaledFont = metrics.scaledFont(for: font, compatibleWith: traitCollection)
let scaledLineHeight = metrics.scaledValue(for: lineHeight, compatibleWith: traitCollection)

let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.minimumLineHeight = scaledLineHeight
paragraphStyle.maximumLineHeight = scaledLineHeight
let attributedString = NSAttributedString(string: text, attributes: [.font: scaledFont, .paragraphStyle: paragraphStyle])

Последний шаг к полной поддержке Dynamic Type – это поддержка валидации всех функций, в том числе находящихся в разработке. Мы знаем, что время разработки ограничено, поэтому мы максимально автоматизировали поддержку Dynamic Type. Happo – инструмент, который мы используем для обнаружения регрессии пользовательского интерфейса, уже создает снимки существующих компонентов. Мы добавили дополнительный шаг для рендеринга с размером accessibilityExtraExtraExtraLarge.

Нет доступных API для программного изменения настроек динамического типа симулятора, поэтому избегайте использования

UIApplication.shared.preferredContentSize. Более тестируемый подход – запросить коллекцию признаков UIView. В окне UIWindow для наших тестов Happo traitCollection настроен для включения нестандартного размера контента. Конечный результат – снимки, подобные этим:

Поддержка Dynamic Type в приложении Airbnb
По умолчанию (большой) предпочтительный размер контента
Поддержка Dynamic Type в приложении Airbnb
AccessibilityExtraExtraExtraLarge preferredContentSize

Снимки файловой системы, создаваемые при каждом изменении кода приложения iOS, позволяют разработчикам легко узнать о новых функциях, поддерживающих Dynamic Type, и легко обнаруживать регрессии.

Спасибо Amie KweonDylan HarrisBryn BodayleTyler Hedrick, и Kieraj Mumick за поддержку этого проекта!


Чтобы опробовать эти функции, загрузите приложение Airbnb в App Store.

Оригинал: Noah Martin & Hugo Ahlberg

Если вы нашли ошибку, выделите фрагмент текста и нажмите Ctrl+Enter

Подпишитесь на рассылку

Раз в неделю мы будем присылать на почту дайджест с лучшими материалами

Похожие записи

Система подбора цветов для интерфейса. Основы. Часть 1

Как создать доступный цифровой опыт Цвет, как инструмент Сегодня мы проводим большую…

Новый подход к подбору цвета интерфейса

Совместное использование нового способа построения цветовых систем для доступных пользовательских интерфейсов. Создайте…

Модульные сетки в цифровых интерфейсах. История, теория, правила использования

Цель этой статьи дать вам хорошее представление о сетках, что это такое и как их применять в процессе проектирования. Понимание того, как использовать сетки сформируется на основе практического опыта.