Пользовательская анимация переходов между экранами

Доброго времени суток. Прошло около года с момента моей первой публикации.

На данный момент времени данная публикация, среди остальных, является самой читаемой, что, естественно, наводит на мысли о дополнении и развитии материала на базе приобретенного опыта разработки. В данной статье вы, как и прежде, найдете решение, позволяющее модально презентовать экран с пользовательской анимацией и, дополнительно, смещать презентованный экран, используя физику реальных объектов — UIKit Dynamics, а также реализовывать эффект сопротивления при оттягивании за установленные пределы — Rubber Band Effect. В примере, для ускорения процесса верстки (упрощения создания constraints) использовалась библиотека SnapKit.

Презентация с пользовательской анимацией

В целях обучения был создан обычный UIViewController с оранжевым фоном и единственной кнопкой “Present”, по нажатию на которую и происходит презентация нового экрана.

При этом данный UIViewController реализует протокол UIViewControllerTransitioningDelegate. Именно реализация данного протокола и позволяет в качестве аниматора указать пользовательский класс. Ссылку на аниматор необходимо сохранять, поскольку ARC удалит данный объект в ином случае и приложение во время презентации закроется.

Класс аниматора опять же, довольно прост в реализации. Для удобства в инициализатор предаются презентующий и презентованный UIViewController, а также свойство isPresenting, отвечающее за то, для чего используется аниматор — презентации или закрытия экрана.

Здесь стоит также обратить внимание на метод animateTransition(using:). Вначале создается snapshot презентующего экрана и добавляется в containerView контекста. Если этого не сделать, то область под презентованным экраном будет пустой. Поверх snapshot уже добавляется view презентованного экрана. Перед запуском анимации презентованному экрану необходимо загрузить view и выполнить процесс layout. На это указывают строки 44 и 45. Сама анимация реализована в презентованном UIViewController, в методе slide(direction:), поэтому достаточно вызвать данный метод в UIView.animate(withDuration:, animation:). В примере вызов данного метода уточнен дополнительными параметрами для того, чтобы добавить пружинящий эффект и возможность взаимодействия во время анимации.

Метод slide(direction:) смещает vContent по вертикали в направлении, которое передается в качестве аргумента методу. Т.е. При презентации vContent расположен за пределами экрана, и смещается вверх на нужную высоту, при закрытии vContent смещается вниз за пределы экрана. Также во время смещения меняется alpha фона, это помогает пользователю фокусироваться на контенте презентованного экрана.

Физика реальных объектов при смещении презентованного экрана

Основываясь на данных проверенного источника (имеется в виду не лесной ручей, а завод-изготовитель, т.е. Apple)

становится очевидным, что для того, чтобы учитывать скорость смещения vContent необходимо использовать UIKitDynamics объекты. Примеров использования данных объектов немало, поэтому стоит лишь вкратце описать, почему использовалась комбинация из трех UIDynamicBehavior.

UIAttachmentBehavior.slidingAttachment(with:attachmentAnchor:axisOfTranslation:) — используется для того, чтобы запретить смещение по горизонтали (задается аргументом axisOfTranslation).

UIDynamicItemBehavior(items:) — используется для того, чтобы придать vContent ускорение (velocity, который определяется UIPanGestureRecognizer), с которым пользователь выполнил смещение. Дополнительно задано сопротивление для того, чтобы смещение было не слишком быстрым.

И, наконец, UISnapBehavior(item:snapTo:) — используется для того, чтобы закрепить объект в нужной точке. При оттягивании объекта, он будет стремиться к заданной точке. Есть более искусный вариант закрепления в точке — это использование UIAttachmentBehavior(item:attachedTo:) вместо snap. Однако это еще тот головосыр, настраивать трение, дистанцию и т.д.

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

Эффект сопротивления при оттягивании за заданные пределы

Как вы, наверняка, могли заметить, в системных приложениях apple реализовано сопротивление, которое усиливается при смещении модального экрана за пределы. Очевидно, что при расчете смещения в формуле участвует логарифм, поскольку чем больше смещение, тем сильнее сопротивление. Немного проштудировав учебник арифметики Древнего Египта и последнее открытие нобелевского лауреата в области астрофизики

, удалось вывести формулу, рассчитывающую смещение с сопротивлением. Конечно, в системе Apple реализовано несколько иное решение (наверняка используется постоянная Планка), но и без этого коэффициента удалось воссоздать достаточно приемлемое решение.

Все достаточно просто, предварительно задаются пределы и далее, при смещении, рассчитываются новые координаты vContent.

Заключение

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

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Ace Rodstin

Ace Rodstin

More from Medium

Protocol Oriented Programming in Swift — Keeping it simple.

Control Flow in Swift

Swift programming: Math

Monad, Functor and Applicatives in Swift