Русский
Русский
English
Статистика
Реклама

Redmadrobot

Дизайнеру приложений как создать и передать в разработку тёмную тему

16.07.2020 12:18:27 | Автор: admin


В конце 2019 года зарелизили iOS 13 и Android 10 с поддержкой автопереключения на тёмную тему. Мы решили добавить её в приложение Ростелеком Ключ под iOS и Android, над которым работали в тот момент. В процессе не обошлось без сложностей. Рассказываем о нашем опыте, чтобы вы в аналогичной ситуации сэкономили время и нервы.

Зачем делать тёмную тему


Может показаться, что это всё на волне хайпа. Но не только :)

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

Если мы выходим из тёмного помещения в светлое, то ненадолго слепнем, но привыкаем к новым условиям уже через 46 минут. Когда же мы переходим из светлого места в тёмное, адаптация занимает больше времени: в среднем 3045 минут. Если человеку постоянно приходится переводить взгляд между ярким приложением и тёмным окружением, адаптация к яркому дисплею будет быстрой, а вот обратная адаптация к темноте медленной.

По этой причине некоторые приложения, например навигаторы, выпустили тёмные темы раньше операционных систем. Если человек едет по дороге ночью, важно, чтобы экран навигатора не отвлекал от движения.

В нашем случае приложение РТ Ключ кросс-платформенный сервис для управления устройствами на территории дома: домофонами, шлагбаумами, камерами видеонаблюдения во дворе и в подъезде. Жители домов используют его как днём, так и ночью.

Справедливо заметить, что тёмная тема также помогает экономить заряд (для некоторых типов экранов: OLED/amoled да, LCD нет). А в долгосрочной перспективе она может замедлить развитие близорукости.

Как перейти на тёмную сторону: пошаговая инструкция


Если вы совсем ничего не знаете о тёмной теме, то можно начать знакомство со статей в Human Interface Guidelines для iOS и в Material Guide для Android. Там подробно разобрано, как цвета и слои взаимодействуют друг с другом в ночном режиме. Перейдём к нашим советам:

1. Приведите в порядок макеты и соберите UI kit

UI kit серьёзно ускоряет работу дизайнера и разработчиков. Обычно мы собираем его сразу после утверждения визуальной концепции на примере нескольких основных экранов приложения. В UI kit входят:

  • Цветовая палитра стилей для обычного состояния элементов, состояния при нажатии, цвета для неактивных элементов, инпутов в фокусе и так далее.
  • Текстовые стили.
  • Все элементы интерфейса (кнопки, поля ввода, элементы списков, блоки с заголовками и так далее) в различных состояниях и ситуациях в виде master components.
  • Сет иконок в черном цвете.
  • Иллюстрации.

UI kit нашего приложения можно рассмотреть в Figma.

Все последующие экраны собираем уже из готовых компонентов. Но при экспорте макетов из Sketch в Figma наш UI kit серьёзно пострадал: пришлось его обновить, заново назначить цветовой стиль для каждого элемента и пересобрать экраны из компонентов.

Все последующие экраны собираем уже из готовых компонентов. Но при экспорте макетов из Sketch в Figma наш UI kit серьёзно пострадал: пришлось его обновить, заново назначить цветовой стиль для каждого элемента и пересобрать экраны из компонентов.

2. Договоритесь о названиях цветов

Чтобы дизайнерам, iOS и Android-разработчикам было проще общаться между собой, цвета мы решили назвать универсально для обеих платформ. В прошлой версии UI kit цветовые стили мы обозначили незатейливо по номерам: C1, C2, C3 Это было не слишком удобно: при обсуждении все называли цвета не по цифрам, а по оттенкам: фиолетовый, оранжевый, чёрный и т. д.

Однако с появлением тёмной темы использовать оттенки в наименовании цветов стало невозможно: например, белый цвет фона в светлой теме сменился на тёмный. Значит, нужно было придумать новый принцип наименований.

После нескольких встреч с участием всей команды определили, что название цвета должно зависеть от его назначения и состоять из следующих частей:

  • Назначение цвета или элемент, на котором он используется.
  • Приоритетность использования (опционально).
  • Состояние элемента, если это применимо (опционально).


Слева наименования для цветов кнопки в обычном состоянии, при нажатии на iOS, цвет Ripple в Android и неактивная кнопка на обеих платформах. Справа имена для текстов на различных поверхностях

В общем, если в вашем проекте ещё нет UI kit, а вместо цветовых стилей назначены обычные цвета, пора причесать макеты.

3. Подберите цвета для тёмной темы

Катя Рокитян, дизайнер Redmadrobot:
Чтобы не тратить драгоценное время, мы не прорабатывали все макеты в тёмной теме, а выбрали только несколько экранов с принципиально различающимися компонентами. С их помощью мы подбирали удачные цвета и добавляли их в палитру. Затем разработчики обновляли цвета в коде приложения, готовили для нас тестовую сборку, а мы изучали, как тёмная тема смотрится живьём. Если выявляли ошибки, правили макеты и палитру.

3.1. Фоновый цвет

Начать перерисовку макета стоит с фонового цвета: он занимает большую часть экрана. В гайдах Material Design советуют брать за основу нейтральный тёмно-серый (#121212). Он, в отличие от черного, оставляет простор для построения глубины экрана.

Фоновый цвет должен хорошо сочетаться с цветом интерактивных элементов: кнопок, иконок и т. д. У нас в светлой палитре для интерактивных элементов использовался фирменный фиолетовый цвет Ростелекома #7700ff. В дальнейшей работе отталкивались от него.

Нейтральный тёмно-серый плохо смотрелся с брендовым фиолетовым, поэтому мы последовали советам гайдлайнов Material Design. Ребята рекомендуют наложить поверх нейтрального фонового серого #121212 фирменный цвет с 8% непрозрачности.


Нейтральные и брендированные цвета фона в тёмной теме

Помимо основного фона у нас встречаются карточки с небольшим подъемом над поверхностью. В Material Design рекомендуют в тёмной теме создавать элевацию элементов за счёт осветления фона: чем ближе карточка к пользователю, тем светлее.

Подобрать подходящие цвета можно, накладывая на фоновый цвет полупрозрачный белый слой. Мы так и сделали.



3.2. Создание базовой палитры

В Material Design рекомендуют при создании брендированной тёмной темы заменять цвета на менее насыщенные аналогичного оттенка. В качестве фирменного цвета для РТ Ключ мы использовали фиолетовый.

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


Оттенок, который мы получили с помощью наложения белого, был слишком розовый сместили тон в сторону синего

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

Navbar и крупные кнопки в осветленной фиолетовой версии особенно сильно отвлекали внимание от контента, а если мы снижали яркость, линейные иконки терялись на тёмном фоне.


В исходной светлой теме насыщенный фиолетовый цвет одинаково хорошо смотрится на крупных блоках с белым текстом и на тонких линейных иконках на светлом фоне. А на тёмном фоне всё не так

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


Заменили один фиолетовый на три так намного лучше

Помимо фиолетового мы использовали оранжевый, желтый, бирюзовый и красный. Оранжевый для call to action элементов, желтый для уведомлений, бирюзовый для подтверждения операции, красный для ошибок.

Когда мы осветлили эти четыре цвета по совету Material Design, серьезно изменилась контрастность приложения по сравнению со светлой темой. Пришлось отступить от гайдов: оранжевый, бирюзовый и красный мы не осветлили, а затемнили. Жёлтый оставили неизменным, поскольку при затемнении он грязнил.



3.3. Особенности палитры iOS

В iOS можно задать оттеночный цвет (он же tint), которым будут окрашены все интерактивные элементы: кнопки, иконки, переключатели и т. д. Например, в настройках iPhone используется синий цвет, а в приложении часы оранжевый.

В светлой теме у нас tint совпадает с цветом больших кнопок, а в тёмной теме мы сделали его чуть светлее, чтобы линейные иконки были хорошо различимы на тёмном фоне.


Оттеночный цвет (tint) в темной теме

В iOS заложена возможность менять цвет интерактивных элементов при нажатии. Это полезно, так пользователю сразу понятно, отреагировало приложение на его действие или нет.

По умолчанию цвет при нажатии становится полупрозрачным. Мы же подумали, что интереснее будет смотреться, если при нажатии кнопки будут углубляться, то есть темнеть.

3.4. Особенности палитры Android

В Android при нажатии на интерактивный элемент от точки прикосновения к нему расходится волна. Этот эффект называет ripple. По умолчанию ripple немного затемняет исходный элемент, а мы хотели его, наоборот, осветлять.

Your browser does not support HTML5 video.

Ripple в Android приложении

Также в Android есть особенности отрисовки status bar и navigation bar. Status bar строка состояния, где отображаются уведомления, уровень сигнала, заряд батареи и время. Navigation bar панель, где располагаются кнопки назад, домой и недавние приложения.

С появлением смартфонов с крупными дисплеями, доходящими до самого края устройства, челками и дырками под камеру, в Material Design представили концепцию edge to edge. Её суть в том, что служебные элементы не должны съедать полезную площадь, и как можно большее место на экране должен занимать полезный контент.

Для этого в Android доработали поддержку прозрачных status bar и navigation bar. Дело в том, что эти панельки не на всех телефонах имеют одинаковую высоту. И если до начала поддержки edge to edge мы назначали им прозрачный фон, на некоторых устройствах они некрасиво накладывались на контент экрана. Теперь в материальных компонентах появились системные отступы: разработчики могут определять размер status bar и navigation bar и задавать соответствующий отступ для контента. Поэтому раньше в Material Design рекомендовали выбирать непрозрачный фон для status bar и navigation bar, а теперь наоборот.

Однако важно учитывать, что не во всех поддерживаемых версиях Android можно назначить цвет иконок в системных компонентах:

  • до 6.0 иконки в status bar и navigation bar всегда белые;
  • с версии 6.0 можно задать, белыми или черными будут иконки в status bar, но navigation bar будет вести себя так, как в предыдущих версиях.
  • с версии 8.1 можно выбрать цвет иконок как в status, так и в navigation bar.

Чтобы избежать странных наложений на контент в Ключе, мы поступили так:

  • в старых версиях Android до 6.0 для обеих панелек задали черный фон с 50% прозрачности на нем хорошо смотрятся белые иконки;
  • с 6.0 и до 8.1 navigation bar остается с полупрозрачным черным фоном, а status bar полностью прозрачный;
  • с версии 8.1 фон обеих панелек полностью прозрачный.

Если вы по каким-то причинам не готовы к такой поддержке edge to edge, лучше сделать status bar и navigation bar универсальными. Поддержка edge to edge:

3.5. Проверьте контрастность элементов

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

Лучше всего проверять контрастность с помощью тестирования: открыть интерфейс на смартфоне, используя Figma Mirror или аналогичный софт, выйти на яркое солнце (тёмная тема предназначена для использования в темноте, но людям ничто не помешает использовать её на свету).

Также будет полезно попросить посмотреть на приложение людей с нарушениями зрения (близорукостью, дальнозоркостью, дальтонизмом). Но если такой возможности нет, контрастность можно проверить на сайте contrast-ratio или с помощью плагина в Figma.

3.6. Иллюстрации и анимации
Если в вашем приложении используются иллюстрации, для тёмной темы их придётся перекрашивать. Насыщенные цвета, которые отлично смотрятся на светлых поверхностях, на тёмных режут глаз и затрудняют восприятие. Используйте менее насыщенные тона.


Для тёмной темы приходится делать отдельные версии иллюстраций и анимаций в тёмных цветах

Как передавать в разработку

Мы работали в связке Figma + Zeplin. Это может показаться странным, но мы всей компанией перешли на Figma из Sketch в конце лета 2019, прямо перед началом работы нам тёмной темой. И чтобы сэкономить время на адаптацию разработчиков к новому инструменту, продолжили работать с Zeplin. И тут он преподнес нам несколько сюрпризов.

В палитре Zeplin нельзя создать цветовые стили с одинаковыми HEX. Поэтому нам пришлось незначительно, практически незаметно для глаза, менять HEX у фиолетового цвета в светлой теме.
Даниил Субботин, iOS-разработчик Redmadrobot subdan:
Обнаружилось, что ни один инструмент дизайнера, в том числе Zeplin, не поддерживает темную тему и поэтому не позволяет иметь несколько цветовых палитр в одном проекте. Пришлось искать пути обхода. Например, мы создали два проекта: один со светлой палитрой, а другой с тёмной.


1. Особенности iOS dev


Следующий сюрприз, который нам преподнес Zeplin: из него можно экспортировать только одну палитру в Xcode-проект. Либо светлую, либо тёмную. При попытке экспортировать цвета тёмной палитры Zeplin просто заменял ими все светлые. Мы стали переносить цвета вручную, копируя HEX-значения. То же самое делали и с изображениями.

Даниил Субботин, iOS-разработчик Redmadrobot subdan:
После долгих мучений я написал утилиту, которая выгружает обе цветовые палитры прямо в Xcode-проект, используя Zeplin API. Это сильно упростило жизнь. Дизайнер сообщает, что добавил новый цвет или изменил старый, я запускаю скрипт, и все изменения автоматически подтягиваются в проект

2. Особенности Android dev


На Android тёмная тема доступна на всех версиях ОС (мы тестировали начиная с пятой). Но переключать её в системе можно только на 10-м Android, поэтому стоит добавить в приложение возможность переключать её вручную.

Владислав Шипугин, android-разработчик Redmadrobot shipa_o:
Мы добавили следующие варианты выбора темы: всегда светлая, всегда тёмная, выбирается в зависимости от режима энергосбережения (9-я версия андроида и ниже), переключается в зависимости от настроек системы (10-я версия андроида и выше). Но важно учесть, что выбранная пользователем тема приложения в системе не сохраняется. Нужно запоминать её внутри и активировать при каждом запуске приложения


В Android есть своя система цветов для материальных компонентов (кнопок, app bar, текстовых полей и т. д.). Гайдлайны Material Design о цвете.

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

Как поддерживать и развивать


С тех пор как мы проработали тёмную тему, у нас добавилось несколько новых функций, появились планшетные пользователи, а продуктовый офис в Ростелекоме задумался о том, чтобы выпустить приложение РТ Ключ в виде white label для застройщиков в их фирменных цветах.

Оля Сартакова, арт-директор Redmadrobot:
Мы поняли, что текущую версию дизайна, разработанную для запуска MVP, пора переосмыслить как структурно, так и визуально. Мы полностью переработали структуру приложения с учетом тех функций, которые должны появиться в ближайшие два года, добавили дашборд для быстрого доступа к самым популярным функциям, избавились от ярких фирменных элементов в оформлении (вроде уголка на главном экране и цветного nav bar). А вот грамотная работа над цветовой системой позволила практически полностью сохранить её при тотальном редизайне приложения.

Вторая версия дизайна приложения в той же цветовой палитре:


Даниил Субботин, iOS-разработчик Redmadrobot subdan:
К моменту запуска второй версии мы безболезненно переехали на Figma, я адаптировал утилиту, которую изначально написал для Zeplin, под Figma. Теперь мы обновляем цвета, иконки и картинки в Xcode и Android Studio в один клик


Скачать нашу утилиту можно здесь.

Выводы: как у нас, только лучше


Если в вашем приложении нужна тёмная тема, её лучше всего заложить на старте, сразу после утверждения визуальной концепции. Это поможет избежать почти всех проблем, с которыми столкнулись мы. Как это делать:

  • Соберите UI kit.
  • Продумайте систему наименования цветов или воспользуйтесь нашей.
  • Подберите брендированный фоновый цвет.
  • Подберите оттенок для основного и второстепенных фирменных цветов.
  • Если ваше приложение кроссплатформенное, составьте список отличий цветовых схем iOS и Android. А также проверьте, не нужно ли добавить в приложение на Android ручную настройку тёмной темы.
  • Проверьте контрастность выбранных цветов.
  • Подготовьте иллюстрации и анимации для тёмной темы.
  • Обновите UI kit.
  • Воспользуйтесь нашей утилитой для передачи элементов в разработку.

Полезные материалы


Чтобы ещё глубже погрузится в тёмную тему:


И немного полезностей для разработчиков:

Подробнее..

Ликбез для дизайнеров с конференции Apple WWDC 2020

10.07.2020 18:18:20 | Автор: admin


Роботы просмотрели обучающие сессии и отобрали полезное для тематического дайджеста Redmadrobot Design Lab.

Учиться и подсматривать за лучшими важная часть нашей работы. Поэтому, как и в предыдущие годы, в этом мы и десятки миллионов разработчиков, дизайнеров и инженеров следили за WWDC. И Keynote от Apple точно задал новую планку для формата онлайн-конференций: все эти классные смены пространств, переключения между спикерами и динамика в нужных моментах.

После вводной презентации началась сама конференция с обучающими лекциями (сессиями) и рабочими консультациями (о том, как всё устроено мы уже писали). И несмотря на название (Worldwide Developers Conference) Apple большое внимание традиционно уделяется дизайну: многие лекции читают дизайнеры и евангелисты, код на их слайдах отсутствует совсем или присутствует в малом количестве.

Евгений Бондарев, креативный директор дизайн-лаборатории Redmadrobot:
Если обратить внимание на то, как Apple презентуют каждую фичу в iPadOS, iOS и др., то мы заметим, что сначала идет рассказ про дизайн и потом про функциональность. Во-первых, это просто красиво, а во-вторых, дизайн создаёт эмоции. И Apple выстраивает взаимодействие с пользователями на уровне эмоций, которые работают в связке с технологиями.

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

iPad


В iPadOS 14 обновили дизайн домашнего экрана, добавили боковую панель навигации, распознавание рукописного текста и более реалистичные AR-объекты.

Отныне на большом экране iPad будет меньше пустого пространства и больше контента. У многих приложений появилась боковая панель для навигации по папкам или вспомогательной информации. Иконки файлов стали меньше, за счет чего на экране iPad может быть на 300% больше контента, чем раньше.



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



Евгений Бондарев, креативный директор дизайн-лаборатории Redmadrobot
Серьезно изменилось взаимодействие с Pencil для iPad Apple добилась почти бесшовного опыта взаимодействия пользователя с планшетом и пером. Например, раньше, чтобы найти что-то нужно было переключиться на клавиатуру, вбить фразу и найти. Сейчас всё стало проще можно написать текст Pencil и функция От руки преобразует его в машинописный. В итоге, практически 99% возможностей доступны с помощью пера, без необходимости использовать клавиатуру.


  • Как именно работать с функцией От руки, Apple рассказывает в сессии Meet Scribble for iPad.
  • Если хочется самому сделать что-то с рисованием карандашом, то можно поглядеть на новые штуки в сессии Inspect, modify, and construct PencilKit drawings.
  • Про проектирование UI для приложений на iPad с поддержкой тач бара и мыши смотрите в сессии Design for the iPadOS pointer.

Также Apple объявили, что приложения для iOS / iPadOS начнут запускаться на новых Маках с процессорами Apple Silicon. Поэтому советуем вам посмотреть на то, как там всё устроено, например, в сессиях What's new in Mac Catalyst и Adopt the new look of macOS.

Евгений Бондарев, креативный директор дизайн-лаборатории Redmadrobot
В этом релизе операционные системы Apple стали более консистентными: iOS стала ближе к iPadOS, а iPadOS ближе к macOS.

Опыт пользователя на Mac и iPad становится все более схожим. С точки зрения UX, боковая файловая структура близка к интерфейсам, которые управляются мышкой. Если есть управление мышкой, то сложно назвать этот интерфейс полностью заточенным под тач.

Функции приложений, которые изначально были для Mac, теперь перетекают в iPad. Из дизайнерских вышла производительная версия Photoshop, есть приложение для работы с Figma. В общем, можно проектировать интерфейсы прямо на планшете. Все эти вещи говорят, что Apple двигается в сторону iPad, который заменит ноутбук для большого числа профессий.


Посмотрите на кнопки и ползунки центра управления в macOS Big Sur. Вам не кажется, что Apple на что-то пытается намекнуть нам?

Подробнее про Sidebar в iPadOS


Прежде мы привыкли видеть на iPad знакомый нам с айфона Tab Bar он позволял переключаться между разделами приложения по нажатию на иконки внизу экрана.



В новой iPadOS дизайнеры Apple предлагают нам иную навигацию с помощью Sidebar. Sidebar размещается слева от контента приложения и не только содержит ссылки на основные разделы экрана, но и позволяет пользователям добавлять их собственные ссылки.

Sidebar на iPad выглядит логичнее Tab Bar-а. Прежний Tab Bar растягивался на всю ширину экрана, из-за чего занимал необоснованно много пространства экрана. Sidebar призван сделать навигацию насыщеннее, персональнее и более похожей на навигацию в macOS.

Несколько советов по проектированию Sidebar:

  • Используйте компонент для верхнеуровневой навигации.
  • Добавьте возможность сворачивать навигацию.
  • Позволяйте пользователям кастомизировать разделы в Sidebar.
  • Поддерживайте Dragndrop.
  • Используйте строуковые (outlined) иконки.

Важно помнить, что нельзя использовать одновременно Tab Bar и Sidebar это собьёт пользователей с толку. Также не забывайте, что на iPhone (Compact Width) мы все также используем Tab Bar как основной инструмент навигации. Подробнее об этом компоненте можно узнать из презентации Design for iPad.

AR и обновленные иконки


Apple представила ARKit 4 с новым Depth API. Сканер LiDAR на iPad Pro 2020 оценивает расстояние до предметов и собирает данные об окружающей среде.



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


Скульптура художника KAWS в приложении Acute Art

Евгений Бондарев, креативный директор дизайн-лаборатории Redmadrobot
Новые иконки приложений стали более объемными, многослойными, у них появились тени. Может показаться, что это шаг в сторону скевоморфизма, но есть подозрение, что эти иконки будут круто смотреться в дополненной реальности. Когда мы начнем взаимодействовать с интерфейсами в пространстве, иконки будут немного двигаться, показывать разные грани. Эта многослойность будет круто работать в пространственных интерфейсах. Это лишь предположение, но уже сегодня мы видим мощную прокачку ARKit. Есть слухи, что уже в следующем году Apple выпустит очки с дополненной реальностью и возможно, обновленные иконки мы увидим уже там.

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

Автомобили



Часть Keynote WWDC про Car Key и пример его работы с BMW (внутри английский)

Евгений Бондарев, креативный директор дизайн-лаборатории Redmadrobot
Apple продолжает активно выходить на рынок ПО для автомобилей. Раньше мы видели Car Play, сейчас представлена интеграция авто с картами Apple Map и цифровой ключ Car Key. С функцией Car Key открывать и закрывать автомобиль можно через iPhone или Apple Watch. При этом разряженное устройство сможет работать еще 5 часов для открытия и закрытия автомобиля. Помимо этого, интеграция с Apple Map позволит при построении маршрута учитывать заряд аккумулятора электромобиля. Всё это сделает iPhone еще более полезным девайсом. За этим могут последовать различные изменения в автомобильной индустрии. Например, вскоре через автомобиль, как гаджет, мы сможем оплачивать покупки, автозаправку и так далее.

Шрифты и символы


Шрифты San Francisco и New York теперь доступны в формате вариативного шрифта. Сочетание разных стилей в одном файле с поддержкой интерполяции позволяет создавать промежуточные стили. При этом созданные шрифты адаптируются для разных размеров. Использование обеих гарнитур поможет создать визуальные иерархии или выделить смысловые различия в контенте. Apple предупреждает, что использование вариативного шрифта на более ранних версиях iOS может привести к неожиданным результатам.

В библиотеке Apple также пополнение 750 новых черно-белых значков и еще 150 цветных. Цветные значки это новинка для SF Symbols 2, они автоматически адаптируются к темной или светлой теме.

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

App Clips


App Clips это мини-приложения, которые можно использовать без установки полной версии. Сейчас для аренды самоката нужно сначала установить приложение, зарегистрироваться, ввести данные для платежа. С App Clip всё проще и быстрее: берем самокат, сканируем QR-код или используем NFC метку, регистрируемся в один клик через Sign in with Apple, оплачиваем аренду через Apple Pay и катаемся себе на здоровье. Если приложение понравилось переходим по ссылке и устанавливаем полную версию.



Другой сценарий оплата парковки в разных городах (в отпуске или командировке), чтобы не скачивать каждый раз новое приложение. Разработчики также предлагают сценарии для интернет-магазинов, кофеен, доставки еды и путешествий. Подробнее в секции от Apple.

Евгений Бондарев, креативный директор дизайн-лаборатории Redmadrobot
App Сlips сильно снижает порог входа для использования мобильных приложений, открывает большие возможности для платформы и сильно влияет на UX, так как можно пользоваться большим числом приложений, просто сканируя код.

Мини-приложения не должны превышать 10 Мбайт, используют SwiftUI и UIkit, имеют доступ к тем же функциям, что и полная версия использование камеры, геолокация, Bluetooth и другие. App Clips могут рассылать push-уведомления в течение суток или, с разрешения пользователя, в течение недели.

Your browser does not support HTML5 video.

Widgets


В iPhone, iPad и Mac добавлены виджеты для главного экрана (Home). По мнению Apple, так главная страница приобретет кардинально новый и более информативный вид, а все самое необходимое будет под рукой. Пользователь может группировать виджеты или использовать автоматическую расстановку, например рекомендованные, недавно открытые.

Your browser does not support HTML5 video.

На iPhone и iPad доступна функция Smart Stack это по сути виджет для виджетов. Позволит объединить виджеты в группу по какому-либо признаку и перелистывать эти группы между собой. Например, утром на главном экране будет группа с погодой и новостями, днем календарь, а вечером карта и информация о пробках.

Виджеты доступны в трех размерах: S, M, L для разной информационной нагрузки. В виджетах используются яркие цвета, фотографии и четкий шрифт, который легко прочесть с первого взгляда.

Пара советов из Widget UI kit: на виджете не нужно указывать название приложения или логотип, только полезный контент. Виджеты должны выглядеть одинаково хорошо в темной и светлой теме. Текст должен быть всегда, но не переводите его в растр, чтобы функция Voice Over работала корректно. Больше информации и советов по использованию виджетов в сессии Apple.

И ещё немного полезного про виджеты можно найти в сессии про возможности операционной системы для решения задач пользователей в различных сценариях (Siri, уведомления, виджеты) Design for intelligence: Discover new opportunities.


Интересные размышления про виджеты и наглядную демонстрацию работы можно подглядеть в обзоре от The Verge.

Новые дизайн-компоненты и не только


В iOS обновлены пикеры, контекстное меню и добавлен выбор цвета.

В Apple переосмыслили визуальный стиль пикеров и взаимодействие пользователя с ними. Выбор даты доступен в 4 режимах: обратный отсчет, время, дата, время и дата. Так будет легче переключаться между годами и месяцами в календаре. Время теперь можно ввести с клавиатуры, а не скроллить переключатель. К пикерам также добавили светло-серый бэкграунд, чтобы выбранный элемент был заметнее. Контекстное меню можно добавить к любой кнопке, при этом меню не будет перекрывать экран смартфона. Сессия о дизайн-компонентах.

Обновление для API SwiftUI упрощает выбор цвета для приложений. У разработчиков теперь есть Color Picker:

  • выбрать цвет из сетки, спектра или с помощью ползунков;
  • изменить прозрачность и переключаться между цветовыми пространствами (Display P3 и sRGB);
  • выбрать цвет из любой точки экрана.
  • О пользовательской палитре Color Picker есть статья на Medium.

Про обновления в watchOS 7, в том числе чем отличается UI на часах и почему именно такие компоненты надо использовать смотрите в сессии Whats new in watchOS design.

И еще несколько сессий по дизайну, менее крутых, по нашему мнению, но можно посмотреть их для вдохновения:

  • Evaluate and optimize voice interaction for your app.
  • Design for location privacy.
  • Design for intelligence: Apps, evolved.
  • Design for intelligence: Make friends with The System.
  • Design for intelligence: Meet people where they are.

Пишите в комментариях, чем вам запомнился этот WWDC. А мы на этом завершаем наш яблочный дизайн-дайджест. Подписывайтесь на Design Jam в Telegram, и да пребудет с вами сила роботов!

P.S. Особые благодарности за участие в подготовке материала выражаем vani2 (Head of iOS Redmadrobot), bealex (CTO Redmadrobot SPb), ex-железному дизайнеру Артуру Абрарову и креативному директору Redmadrobot Жене Бондареву.

P.P.S. И напоследок ещё пример UX-магии от Apple, замеченной после выхода беты iOS 14

With Back Tap, you can perform various action by double or tripple tap on the back of your iPhone. Heres one I set double tap to take screenshot. pic.twitter.com/uZKv4Cjorf

Aditya Daniel (@adityadaniel) June 23, 2020
Подробнее..

Автоматизация тестирования продуктовой аналитики в мобильных приложениях

12.10.2020 12:10:07 | Автор: admin

Тестирование всех событий продуктовой аналитики перед каждым релизом обычно отнимает много времени. Это можно автоматизировать. Показываю, как именно, на примере iOS-приложения.

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

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

Тестирование аналитики вручную

Когда пользователь совершает действие, то событие аналитики сразу отправляется в систему аналитики. И, к сожалению, это никак не отследить, чтобы протестировать. Только если модифицировать код приложения, чтобы вместе с отправкой события сделать дополнительное действие. Какие есть варианты:

  1. Можно отправить локальное уведомление (типа Push) с названием и параметрами события. Это неудобно, так как перекрывает интерфейс приложения, а также сложно тестировать цепочку событий из-за того, что каждое новое уведомление перекрывает старые.

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

  3. Либо события аналитики можно логировать и сразу отслеживать в консоли.

События аналитики в Console.appСобытия аналитики в Console.app

Третий вариант самый удобный: его несложно сделать и он позволяет фильтровать события. Также при тестировании приложения сразу видно, какие события отправляются. И если приложение содержит небольшое количество событий, то этим вариантом можно обойтись, не прибегая к автоматизации.

Это всё способы тестирования события аналитики вручную. Но если в приложении событий много, то такое тестирование будет не быстрым.

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

Тестирование аналитики UI-тестами

У любого события есть имя, у некоторых бывают еще и параметры. Например, у успешность авторизации имя authorization и булевый параметр success.

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

На практике есть два способа передачи данных из приложения в UI-тесты:

  • Можно сохранить текстовые данные в невидимое текстовое поле или в свойство accessibilityLabel невидимой вьюшки. Но в этом случае меняется иерархия вьюшек, и это может привести к багам. Кроме того, не получится очистить список отправленных событий из UI-тестов.

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

Когда приложение запущено в режиме UI-тестирования, то можно подменить сервис отправки событий аналитики. Например, вместо AppMetrica подставить свой сервис, который будет отправлять события в буфер обмена. Далее в UI-тестах происходит чтение текстовых данных из буфера, преобразование их в массив событий и проверка.

Так в итоге будет выглядеть UI-тест, проверяющий события аналитики на экране авторизации:

func testLoginSuccess() {    // Запустить приложение    launchApp()        // Проверить что отправилось событие показа экрана авторизации    analytics.assertContains(name: "open_login_screen")        // Успешно залогиниться    loginScreen.login(success: true)        // Проверить что отправилось событие успешной авторизации    analytics.assertContains("authorization", ["success": true])}

Доработки со стороны приложения

Расскажу о том, как доработать код приложения, чтобы события аналитики отправлялись и в систему аналитики, и в буфер обмена в зависимости от переданных аргументов при запуске приложения.

Базовые сущности

Представим событие аналитики в виде следующей структуры:

public struct MetricEvent: Equatable {     public let name: String        public let values: [String: AnyHashable]?     public init(name: String, values: [String: AnyHashable]? = nil) {        self.name = name        self.values = values    }}

Структура MetricEvent будет использоваться и в коде приложения, и в коде UI-тестов. Поэтому вынесем её в отдельный модуль MetricExampleCore. Для этого нужно создать новый Target типа Framework.

Событие что-то должно отправлять, поэтому объявим соответствующий протокол:

import MetricExampleCore /// Сервис отправки событий в аналитикуpublic protocol MetricService {        func send(event: MetricEvent)    }

В первой строчке импортируем модуль, в котором объявили структуру MetricEvent.

Сервисы отправки событий

Этому протоколу будут соответствовать классы, отправляющие события куда-либо. К примеру, класс для отправки событий в AppMetrica:

import Foundationimport MetricExampleCoreimport YandexMobileMetrica open class AppMetricaService: MetricService {     public init(configuration: YMMYandexMetricaConfiguration) {        YMMYandexMetrica.activate(with: configuration)    }     open func send(event: MetricEvent) {        YMMYandexMetrica.reportEvent(event.name, parameters: event.values, onFailure: nil)    }}

В нашем случае нужен класс, который отправляет события в буфер обмена. Создаем его:

import Foundationimport MetricExampleCoreimport UIKit final class MetricServiceForUITests: MetricService {     // Массив всех отправленных событий аналитики    private var metricEvents: [MetricEvent] = []     func send(event: MetricEvent) {        guard ProcessInfo.processInfo.isUITesting,              ProcessInfo.processInfo.sendMetricsToPasteboard else {            return        }                if UIPasteboard.general.string == nil ||           UIPasteboard.general.string?.isEmpty == true {            metricEvents = []        }         metricEvents.append(event)         if let metricsString = try? encodeMetricEvents(metricEvents) {            UIPasteboard.general.string = metricsString        }    }     private func encodeMetricEvents(_ events: [MetricEvent]) throws -> String {        let arrayOfEvents: [NSDictionary] = events.map { $0.asJSONObject }        let data = try JSONSerialization.data(withJSONObject: arrayOfEvents)        return String(decoding: data, as: UTF8.self)    }}

В методе send можно проверить, что приложение запущено в режиме UI-тестирования и разрешена отправка событий в буфер обмена. Затем в массив всех отправленных событий добавляется новое.

После этого массив представляется в виде текста с использованием метода encodeMetricEvents. Там каждое событие преобразуется в словарь и полученный массив сериализуется. После этого строка сохраняется в буфер обмена.

// MetricEvent.swift...    /// Представляет событие в виде словаря для передачи в JSONSerialization.data(withJSONObject:)    public var asJSONObject: NSDictionary {        return [            "name": name,            "values": values ?? [:]        ]    }...

Каждый UIViewController, который будет отправлять события, получит в инициализатор зависимость MetricService.

final class LoginViewController: UIViewController {        private let metricService: MetricService        init(metricService: MetricService = ServiceLayer.shared.metricService) {        self.metricService = metricService        super.init(nibName: nil, bundle: nil)    }    ...

Чтобы не передавать каждый раз вручную эту зависимость, можно использовать паттерн Service Locator и создать класс ServiceLayer. В нем будет создаваться и храниться MetricService, который будет передаваться во все контроллеры.

import Foundationimport YandexMobileMetrica final class ServiceLayer {        static let shared = ServiceLayer()        private(set) lazy var metricService: MetricService = {        if ProcessInfo.processInfo.isUITesting {            return MetricServiceForUITests()        } else {            let config = YMMYandexMetricaConfiguration(apiKey: "APP_METRICA_API_KEY")            return AppMetricaService(configuration: config)        }    }()}

Если приложение запущено в режиме UI-тестирования, то для отправки событий используется MetricServiceForUITests. В ином случае AppMetricaService.

Отправка событий

Осталось объявить все события, которые будут отправляться. Для этого нужно написать расширение MetricEvent:

import Foundationimport MetricExampleCore extension MetricEvent {        /// Пользователь перешел на экран авторизации    static var openLogin: MetricEvent {        MetricEvent(name: "open_login_screen")    }     /// Пользователь ввел логин и пароль и инициировал авторизацию.    ///    /// - Parameter success: Успешность запроса.    /// - Returns: Событие метрики.    static func authorization(success: Bool) -> MetricEvent {        MetricEvent(            name: "authorization",            values: ["success": success]        )    }}

Теперь события можно отправлять:

metricService.send(event: .openLogin)metricService.send(event: .authorization(success: true))metricService.send(event: .authorization(success: false))

Аргументы запуска

Я уже упоминал такие вещи, как:

ProcessInfo.processInfo.isUITestingProcessInfo.processInfo.sendMetricsToPasteboard

При запуске UI-тестов на аналитику будут передаваться два аргумента: --UI-TESTING и --SEND-METRICS-TO-PASTEBOARD. Первый показывает, что приложение запущено в режиме UI-тестирования. Второй что приложению разрешено отправлять события аналитики в буфер обмена. Чтобы получить доступ к этим аргументам, нужно написать расширение для ProcessInfo:

import Foundation extension ProcessInfo {    var isUITesting: Bool { arguments.contains("--UI-TESTING") }    var sendMetricsToPasteboard: Bool { arguments.contains("--SEND-METRICS-TO-PASTEBOARD") }}

Доработки со стороны UI-тестов

Теперь расскажу, как на стороне UI-тестов получить список отправленных событий из буфера обмена и проверить их.

Получение списка отправленных событий

Чтобы получить текстовые данные из буфера, используем UIPasteboard.general.string. Затем строку нужно преобразовать в массив событий (MetricEvent). В методе decodeMetricEvents строка преобразуется в объект Data и десериализуется в массив с помощью JSONSerialization:

/// Возвращает список всех событий аналитики произошедших с момента запуска приложенияfunc extractAnalytics() -> [MetricEvent] {    let string = UIPasteboard.general.string!    if let events = try? decodeMetricEvents(from: string) {        return events    } else {        return []    }} /// Преобразует строку с массивом событий в массив объектов [MetricEvent]private func decodeMetricEvents(from string: String) throws -> [MetricEvent] {    guard !string.isEmpty else { return [] }    let data = Data(string.utf8)     guard let arrayOfEvents: [NSDictionary] = try JSONSerialization.jsonObject(with: data) as? [NSDictionary] else {        return []    }     return arrayOfEvents.compactMap { MetricEvent(from: $0) }}

Далее массив словарей преобразуется в массив MetricEvent. Для этого у MetricEvent нужно добавить инициализатор из словаря:

/// Пытается создать объект MetricEvent из словаряpublic init?(from dict: NSDictionary) {    guard let eventName = dict["name"] as? String else { return nil }    self = MetricEvent(        name: eventName,        values: dict["values"] as? [String: AnyHashable])}

Теперь можно получить массив событий [MetricEvent] и проанализировать его.

Если в процессе тестирования понадобится очистить список событий, то тут поможет:

UIPasteboard.general.string = ""

Проверки списка событий

Можно написать несколько вспомогательных методов, которые будут проверять массив событий. Вот один из них: он проверяет наличие события с указанным именем.

/// Проверяет наличие события с указанным именем/// - Parameters:///   - name: Название события///   - count: Количество событий с указанным именем. По умолчанию равно 1.func assertContains(    name: String,    count: Int = 1) {     let records = extractAnalytics()     XCTAssertEqual(        records.filter { $0.name == name }.count,        count,        "Событие с именем \(name) не найдено.")}

В итоге получился класс AnalyticsTestBase. Посмотреть его можно на GitHub AnalyticsTestBase.swift

Создадим класс, наследника XCTestCase, от которого будут наследоваться классы, тестирующие аналитику. Он создает класс AnalyticsTestBase для тестирования аналитики и метод launchApp, запускающий приложение.

import XCTestclass TestCaseBase: XCTestCase {        var app: XCUIApplication!    var analytics: AnalyticsTestBase!        override func setUp() {        super.setUp()                app = XCUIApplication()        analytics = AnalyticsTestBase(app: app)    }        /// Запускает приложение для UI-тестирования с указанными параметрами.    func launchApp(with parameters: AppLaunchParameters = AppLaunchParameters()) {        app.launchArguments = parameters.launchArguments        app.launch()    }}

Метод будет принимать AppLaunchParameters (параметры запуска приложения, о которых я говорил выше).

struct AppLaunchParameters {        /// Отправлять аналитику в UIPasteboard    private let sendMetricsToPasteboard: Bool        init(sendMetricsToPasteboard: Bool = false) {        self.sendMetricsToPasteboard = sendMetricsToPasteboard    }        var launchArguments: [String] {        var arguments = ["--UI-TESTING"]        if sendMetricsToPasteboard {            arguments.append("--SEND-METRICS-TO-PASTEBOARD")        }        return arguments    }}

В обычных UI-тестах приложение будет запускаться с параметрами:

AppLaunchParameters(sendMetricsToPasteboard: false)

А в UI-тестах на аналитику:

AppLaunchParameters(sendMetricsToPasteboard: true)

Теперь можно писать тесты на аналитику. Например, это тест на экран входа:

final class LoginAnalyticsTests: TestCaseBase {        private let loginScreen = LoginScreen()        func testLoginSuccess() {        launchApp(with: AppLaunchParameters(sendMetricsToPasteboard: true))                // Проверить что отправилось событие показа экрана входа        analytics.assertContains(name: "open_login_screen")                // Успешно залогинится        loginScreen.login(success: true)                // Проверить что отправилось событие успешной авторизации        analytics.assertContains("authorization", ["success": true])    }}

LoginScreen это Page Object, описывающий экран авторизации. Посмотреть его можно на GitHub LoginScreen.swift

Примеры

Example проект

iOS-проект, где используется автоматизированное тестирование аналитики UI-тестами.

Это простое приложение, состоящее из двух экранов: вход и меню. События отправляются при заходе на каждый экран, при авторизации и при выборе пункта меню.

Тест, покрывающий все эти события:

import XCTest final class AnalyticsTests: TestCaseBase {        private let loginScreen = LoginScreen()    private let menuScreen = MenuScreen()        // MARK: - Login        func testLoginSuccess() {        launchApp(with: AppLaunchParameters(sendMetricsToPasteboard: true))                analytics.assertContains(name: "open_login_screen")        loginScreen.login(success: true)         analytics.assertContains("authorization", ["success": true])    }        func testLoginFailed() {        launchApp(with: AppLaunchParameters(sendMetricsToPasteboard: true))                analytics.assertContains(name: "open_login_screen")        loginScreen.login(success: false)        analytics.assertContains("authorization", ["success": false])    }        // MARK: - Menu        func testOpenMenu() {        launchApp(with: AppLaunchParameters(sendMetricsToPasteboard: true))         loginScreen.login(success: true)        waitForElement(menuScreen.title)        analytics.assertContains(name: "open_menu_screen")    }        func testMenuSelection() {        launchApp(with: AppLaunchParameters(sendMetricsToPasteboard: true))                loginScreen.login(success: true)        waitForElement(menuScreen.title)         menuScreen.profileCell.tap()                analytics.assertContains("menu_item_selected", ["name": "Профиль"])                menuScreen.messagesCell.tap()        analytics.assertContains("menu_item_selected", ["name": "Сообщения"])    }}

Реальный проект

Пример UI-тестов на аналитику экрана авторизации из реального проекта LoginAnalyticsTests.swift

Пример, как мне, разработчику, помогли UI-тесты на аналитику. На одном проекте нужно было произвести рефакторинг и редизайн главного экрана приложения. Экран был сложным, с большим количеством событий аналитики. На тот момент в проекте я уже настроил тесты. После рефакторинга и редизайна запустил тесты и обнаружил, что некоторые события случайно удалил. Если бы не тесты на аналитику, эти события не попали бы в релиз.

Итоги

Плюсы подхода:

  1. Продуктовому аналитику или тестировщику не нужно проверять все события аналитики вручную. А это экономия времени и, соответственно, денег.

  2. Если у вас настроен CI, то UI-тесты на аналитику можно запускать по расписанию, например, раз в неделю или по команде из Slack.

Есть и минусы:

  1. UI-тесты выполняются относительно долго. Имеет смысл запускать их только в процессе регрессионного тестирования перед каждым релизом.

  2. UI-тесты на аналитику смогут написать только те тестировщики, которые имеют опыт написания нативных UI-тестов.

В случае ручного тестирования, при добавлении новых событий, нужно линейно больше времени на тестирование. Автоматизированное тестирования быстрее, но для него нужно подготовить инфраструктуру: это займет некоторое время. Но после этого добавление теста на новое событие будет проходить быстрее.

Поэтому в случае большого проекта есть смысл автоматизировать проверку событий аналитики.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru