7 сентября 2016 г. Анимация в iOS: нативные решения и сторонние фреймворки

7 сентября 2016 г. Анимация в iOS: нативные решения и сторонние фреймворки

Всем привет! Сегодня мы будем рассматривать анимацию в iOS. Взглянем на несколько довольно-таки легких примеров, пройдемся по преимуществам и недостаткам того, что предлагает нам Apple и также рассмотрим несколько, на мой взгляд, достойных фреймворков сторонних разработчиков. Кроме того, я покажу примеры использования UIKit Dynamics и Motion Effects, которые доступны с версии iOS 7.

UIKit Dynamics — это физический движок, позволяющий воздействовать на элементы путем добавления поведений ( behaviors ), таких как gravity , springs , forces , и т.д. А движок при этом уже сам заботится обо всем остальном.

Motion Effects — позволяет вам создавать parallax effects, которые мы, например, видим на рабочем столе, когда немного поворачиваем телефон. Home screen при этом будто бы немного сдвигается в одну сторону, а иконки — в противоположную. За счет этого создается эффект глубины, который вы без особого труда можете использовать в своих приложениях.

UIKit Dynamics

Добавим в storyboard UIView , дадим ему серый цвет и привяжем его с помощью constrains . Тут нужно быть внимательными, так как иногда физический движок плохо воспринимает такую привязку, поэтому нужно просто добавить элемент где-нибудь в viewDidLoad() и задать размер с помощью frame .

Далее добавляем несколько свойств в класс ViewController :

В viewDidLoad() инициализируем эти свойства:

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

Добавляем UICollisionBehavior и ставим его свойство translatesReferenceBoundsIntoBoundary в true . Это свойство отвечает за границы системы, если его значение true — границами будут view нашего ViewController ’а. Не забываем добавить наше новое поведение к объекту animator — он проводит все расчеты:

Теперь серый квадрат ударяется о нижнюю часть экрана — отлично!

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

Барьер добавлен, сейчас нужно добавить collision :

Теперь все отлично, система работает, кубик падает и происходит столкновение. Идем дальше и добавим кубику немного «эластичности»:

Кроме параметра elasticity , в нашем арсенале есть еще пару свойств с которыми можно поиграться:

  • elasticity
  • friction
  • density
  • resistance
  • angularResistance

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

И реализуем следующий метод:

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

Теперь поговорим о том, что происходит за сценой. Каждое поведение ( behavior ) имеет свойство action . Мы можем добавить блок кода, который наша анимация будет выполнять во время каждого шага (около 400 миллисекунд). Добавим:

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

Так будет выглядеть финальный результат:

Motion Effects

Для следующего примера желательно иметь реальный девайс. На симуляторе повторить этот эффект не удастся, можете не стараться наклонять голову или монитор — я пробовал, ничего не вышло :)

Так выглядит наш storyboard:

Также обратите внимание на constraints для backImView :

Сделано это для того, чтобы при сдвиге backImView (картинка с небом) не показывала белый цвет view контроллера. А теперь код:

Мы добавим motion effect к заднему виду ( backImView ) и к фронтальному ( frontImView ). midImView нам не интересен, он остается статичным.

Создаем вспомогательный метод addMotionEffectToView и инициализируем его нашими UIImageView с дополнительными свойствами — и все! Хорошего вам parallax-эффекта )

Начнем с рассмотрения сторонних фреймворков. Первой «жертвой» нашего обзора будет фреймворк Pop от Facebook. Вдобавок к стандартной анимации ( POPBasicAnimation ) фреймворк поддерживает POPSpringAnimation и POPDecayAnimation , что позволяет добиться реалистичной и физически корректной анимации.

Для примера будем использовать cocoapods. Добавляем в Podfile:

В storyboard добавлено несколько элементов и segue для перехода на экран со скотч-терьером, смотрим и умиляемся :)

По клику на каждый элемент происходит конкретная анимация. Начнем c метода animateLabel() :

Вначале создаем объект POPSpringAnimation , инициализировав его именем того свойства, с которым будем работать. По клику на kPOPLayerScaleX перейдите к файлу, в котором увидите список всех свойств, которые можете анимировать.

Обратите внимание, что можно анимировать как CALayer property names, так и UIView property names — от этого зависит, будем ли мы применять анимацию к объекту или его слою. completionBlock я добавил просто для наглядности, чтобы знать когда закончится анимация.

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

Ключ может быть произвольным. В итоге наш UILabel-объект начинает растягиваться по оси Х.

По клику на UISegmentedControl запускаем мигающую анимацию свойства alpha.

Продвигаемся к более сложному примеру:

Опять будем использовать POPSpringAnimation и, на этот раз, анимировать kPOPLayerBounds . Эта анимация отвечает за изменения размеров (frame) UIView . Вначале мы придаем UIView вид, похожий на status bar.

Далее анимируем cornerRadius — тут используем просто POPBasicAnimation . И подписываемся делегатом на pop_animationDidStop . Реализовываем сам метод:

Далее в теле метода вызываем еще одну анимацию:

В итоге у нас выходит вот такая вот метаморфоза простого оранжевого кубика в status bar :)

И последний вид анимации, который я хотел бы рассмотреть, это custom segue animation.

Вот как создание подобного segue выглядит в storyboard:

CustomSegue — это класс, унаследованный от UIStoryboardSegue , который отвечает за анимацию при переходе между контроллерами.

Чтобы сделать простую анимацию, мы перепишем всего один метод:

В итоге нам удалось немного оживить анимацию. Конечно, в реальном приложении нам пришлось бы еще подчиняться протоколу UIViewControllerTransitioningDelegate и реализовывать два его метода: animationControllerForPresentedController и animationControllerForDismissedController . Тут я лишь хотел показать, как относительно легко можно добиться желаемого результата с использованием фреймворка Pop.

Cheetah

Лично мне очень понравился фреймворк Cheetah. Он удивительно компактный в плане кода и дает вполне приличные результаты.

Откройте проект Cheetah_project. В storyboard у нас содержится всего одна кнопка, по которой мы и будем кликать все время :) Код самой кнопки показан ниже:

И, прописав всего несколько строчек кода, мы получаем анимацию, на которую стандартными методами потратили бы намного больше времени. А главное, чем больше у вас написано кода, тем сложнее его править.

Также советую обратить внимание на framework Spring. Разработчики подготовили очень приятное приложение, с помощью которого вы можете исследовать возможности их продукта и даже смотреть на код, заинтересовавшего вас эффекта. А также на DCAnimationKit — очень простой в использовании framework с кучей уже готовых решений.

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

Или, по крайней мере, вы должны знать методы уже более «высокого» уровня, такие как:

  • UIView.animateWithDuration
  • UIView.animateKeyframesWithDuration
  • UIView.addKeyframeWithRelativeStartTime

А также понимать, что такое CABasicAnimation() , CAPropertyAnimation() и т.д.

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

Нужен MVP, разработка под iOS, Android или прототип приложения? Ознакомьтесь с нашим портфолио и сделайте заказ уже сегодня!

📎📎📎📎📎📎📎📎📎📎