Анимации c помощью Transitions API

Всем привет! На хабре ещё не была освещена тема Transitions API для анимаций, которые появились в Android начиная с 4.4 (KitKat) и продолжили свое развитие в 5.0 (Lollipop). В своей статье я расскажу о том, как упростить работу с анимациями с их использованием и как применять их на любом устройстве с версией Android 3.0 и выше.

imageВместе с Android 4.4 был представлен новый механизм анимации изменений в layout. Ещё в версии 4.0 появился первый вариант решения этой проблемы — флаг animateLayoutChange для ViewGroup. Но даже с вызовом метода getLayoutTransition () и изменением его параметров он был недостаточно гибок и не давал полного контроля над тем, как будет анимироваться наше изменение (transition).

KitKat Transition API приносит нам понятия сцены — Scene и некоторого изменения между сценами — Transition. В добавок к ним вводим понятие Scene root для определения корневого layout, внутри которого будут происходить изменения сцен. А сама сцена это некоторый враппер над ViewGroup, который описывает конкретное состояние его самого и всех содержащихся в нем объектов View.

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

Начнем с самого простого варианта использования Transitions API.Представим, что текущее состояние нашего layout это первая сцена. Допустим у нас просто изображен квадрат.Опишем layout через xml:

Теперь мы просто хотим анимированно увеличить размер нашего квадрата. Чтобы уже начать привыкать к понятию сцен назовем это изменение переходом ко второй сцене. ViewGroup sceneRoot = (ViewGroup) findViewById (R.id.container); View square = mSceneRoot.findViewById (R.id.transition_square); int newSquareSize = getResources ().getDimensionPixelSize (R.dimen.square_size_expanded);

// вызываем метод, говорящий о том, что мы хотим анимировать следующие изменения внутри sceneRoot TransitionManager.beginDelayedTransition (sceneRoot);

// и применим сами изменения ViewGroup.LayoutParams params = square.getLayoutParams (); params.width = newSquareSize; params.height = newSquareSize; square.setLayoutParams (params); Результат: image

Неплохо, анимация всего одной строкой. Причем таких изменений внутри layout может быть любое количество.Теперь попробуем настроить некоторые параметры анимации. Для этого нужно указать конкретный Transition, который мы будем выполнять. Метод beginDelayedTransition может принимать вторым параметром любого наследника класса Transition. Именно про них мы сейчас и поговорим.

Простые типы Transition ChangeBounds. Именно он выполнялся в первом примере. Это Transition, который отвечает за изменение координат View внутри layout и его размеров. Fade. Объединяет в себе всем известные анимации fade in и fade out. Он является наследником класса Visibility, который придуман для тех Transition, которые выполняются в тот момент, когда View была видна в первой сцене, но должна исчезнуть при переходе во вторую, или же, наоборот, появиться. TransitionSet. Тоже является наследником Transition, однако представляет из себя всего лишь набор какого-либо количества других Transition, которые выполняются по очереди или одновременно. Очередность устанавливается с помощью метода setOrdering. AutoTransition. Он является таким TransitionSet, который всего лишь является набором из последовательно выполняющихся Fade с параметром Fade.OUT, ChangeBounds и Fade с параметром Fade.IN. Таким образом, сначала с fade out эффектом прячутся все View, которых нет во второй сцене, потом происходит перемещение и изменение размеров для View, у которых эти параметры изменились, и, наконец, с fade in появлятся новые элементы из второй сцены. Именно AutoTransition выполняется, когда мы, как и в первом примере, не указали никакого конкретного Transition методу beginDelayedTransition. Сцены Вернемся к сценам. В первом примере мы разобрали самый простой способ использования API. Но сцены можно описывать и более формально, например, чтобы было удобнее между ними переключаться.Опишем layout нашего Activity так, чтобы в нем была кнопка для смены сцен и FrameLayout, который будет нашим Scene root. Внутрь его сразу ставим layout, который является первой сценой, но вынесем его в отдельный файл.