UXPUB 🇺🇦 Дизайн-спільнота

Cover image for О создании гибкого пользовательского интерфейса на примере Instagram Threads
Редакція
Редакція

Опубліковано

О создании гибкого пользовательского интерфейса на примере Instagram Threads

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

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

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

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

Адаптивные кнопки

Кнопки являются одними из самых основных компонентов любого интерфейса, и тем не менее, во время разработки о них редко задумываются. На самом деле кнопки в UIKit на удивление мало изменились со времен iOS 7, когда Apple отказалась от первоначального скевоморфного дизайна.

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

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

  • Физическое свойство – реакция должна быть физической. Кнопка должна нажиматься при касании и подниматься при отпускании. Для этого мы использовали анимацию масштабного преобразования (scale transform).
  • Пропорциональное свойство – ответ должен быть пропорционален количеству введенных данных. Длительное нажатие должно отличаться от быстрого. Для этого мы использовали аниматоры прерываемых свойств (interruptible property animators).
  • Тактильное свойство – реакция должна быть тактильной. Кнопка должна обеспечивать ощутимую обратную связь, когда вы с ней взаимодействуете. Для этого мы использовали легкую тактильную обратную связь.

Это взаимодействие кнопок реализовано через расширение UIView. Внутри любого UIView вы можете переопределить протокол под названием UIResponder, который дает вам доступ к touch-событиям, позволяя реализовать любое настраиваемое поведение, которое захотите.

Масштабные преобразования реализованы путем применения стандартных CGAffineTransforms к слою представления, а анимации реализованы с использованием прерываемых UIViewPropertyAnimators с параметрами spring timing для плавной кривой анимации.

Эластичный скролл

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

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

Этот механизм эластичного скролла реализован с помощью настраиваемого UICollectionViewFlowLayout.

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

Здесь стоит отметить одну деталь: для компонентов, которые можно нажимать в UIScrollView, в момент, когда пользователь касается элемента, еще неясно, является ли жест жестом тапом или началом скролла.

Для стандартных ячеек в UITableView или UICollectionView, где реакция на прикосновение по умолчанию заключается в настройке цвета фона ячейки, чтобы указать, когда она выделена, немедленная обработка касания может вызвать неприятные ощущения, потому что ячейка под пальцем пользователя будет мигать каждый раз, когда он начинает скроллить. Стандартное решение UIKit – отложить обработку касаний в контексте скролла до тех пор, пока не станет ясно, какова цель жеста – довольно неэлегантное решение. В каждом UIScrollView есть соответствующее свойство, называемое delaysContentTouches, для которого по умолчанию установлено значение true.

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

Это незначительная деталь, но она делает этот тип взаимодействия более отзывчивым.

Плавная навигация

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

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

Ключом к этому стилю перехода является концепция настраиваемых зеркальных представлений (mirror views). Это представления, которые представляют определенные элементы контента и поддерживают различные конфигурации макета (например, ячейку почтового ящика и заголовок треда) с возможностью плавной анимации между ними. Во время переходов эти представления используются для отражения исходного и целевого контента в начале и конце перехода соответственно, создавая впечатление, что интерактивный компонент фактически расширяется, заполняя экран.

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

Вместо стандартного presentViewController:animated:completion: interface входные параметры этой презентации представляют собой серию настраиваемых блоков кода, которые определяют, как должен работать переход. Есть блоки для настройки исходного представления, целевого представления, зеркального представления и перехода зеркального представления, а также для настройки дополнительных представлений в начале и в конце перехода. Внутри fluid presentation dispatcher функционирует как конечный автомат, выполняя каждый соответствующий блок в координации с различными этапами анимации перехода.

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

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

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

Динамичеcкие темы

Мы с самого начала знали, что хотим добавить в Threads темы. Но имейте в виду, что это было еще в конце 2018 года, задолго до того, как темная тема была добавлена в приложение Instagram (об этом есть отличный пост).

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

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

Используя appearance provider class, который передает цвета текущей темы, мы привязываем отдельные объекты к заданному блоку кода во время инициализации, в которой мы настраиваем свойства представления, зависящие от темы (например, цвет фона, цвет текста и т. д.). Полагаясь на NSNotificationCenter, эта система сообщает об обновлениях темы каждому appearance provider, который, в свою очередь, при необходимости вызывает блок конфигурации каждого представления.

Это относительно простая система, но она оказалась эффективным способом управления темами.

Вывод

Threads во многом является продуктом более широкой культуры Instagram. Мы придаем большое значение мастерству и твердо верим, что детали важны, когда вы создаете продукты, которыми пользуются миллионы людей. У нас сильная культура прототипирования, которая позволяет нашим самым креативным разработчикам и дизайнерам делать свою работу наилучшим образом, зачастую руководствуясь энтузиазмом, а не дорожной картой. Эти качества отражаются в нашей работе, и Threads – отличное напоминание о том, почему это важно.

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


Перевод статьи about.instagram.com

Найновіші коментарі (0)