Наш конечный продукт будет достаточно прост. Мы будем делать приложение-галерею с котиками. При нажатии на изображение будет открываться экран с подробностями. Благодаря фреймворку переход из сетки изображений в окно с подробностями будет сопровождаться анимацией.
Если вы желаете увидеть, что получилось — готовое приложение находится на GitHub.
Поддержка предыдущих версий Android?
У меня есть для вас две новости: хорошая и плохая. Плохая новость заключается в том, что до Lollipop данный фреймворк не работает. Не смотря на это, проблема решается методами библиотеки поддержки с помощью которой вы можете реализовать анимированые переходы доступные в API 21+.
В статье будут использоваться функции из библиотеки поддержки для обеспечения перемещения контента.
Имена переходов
Для ассоциации View на первом экране и его двойника на втором нужна связь. Lollipop предлагает использовать свойство “transition name” для связи
View
между собой.Существует два способа добавления имени перехода (transition name) для ваших View:
- В коде можно использовать
ViewCompat.setTransitionName()
. Конечно, вы так же можете просто вызватьsetTransitionName()
, если поддержка начинается с Lollipop. - Для добавления в XML, используйте атрибут
android:transitionName
.
Важно отметить, что внутри одного макета (layout), имена переходов должны быть уникальны. Держите это в уме при организации переходов. Указывая transition name для
ListView
или RecyclerView
задаст это же имя и для всех остальных элементов.Настройка FragmentTransaction
Настройка
FragmentTransactions
должна быть вам очень знакомой:getSupportFragmentManager()
.beginTransaction()
.addSharedElement(sharedElement, transitionName)
.replace(R.id.container, newFragment)
.addToBackStack(null)
.commit();
Чтобы указать какую View будем передавать между фрагментами — используем метод
addSharedElement()
.Переданная View в
addSharedElement()
это View из первого фрагмента, которую вы хотите разделить (share) со вторым фрагментом. Имя перехода тут является именем перехода в разделенной (shared) View во втором фрагменте. Настройка анимации перехода
Наконец-то пришел момент, когда мы зададим анимацию перехода между фрагментами.
Для
shared
элементов:- Для перехода с первого фрагмента во второй используем метод
setSharedElementEnterTransition()
. - Для возврата назад используем метод
setSharedElementReturnTransition()
. Анимация произойдет при нажатии кнопки назад.
Заметьте, что вам необходимо вызвать эти методы во втором фрагменте, поскольку, если вы сделаете это в первом — ничего не произойдет.
Вы так же можете анимировать переходы для всех non-shared View. Для этих View, используйте
setEnterTransition()
, setExitTransition()
, setReturnTransition()
, и setReenterTransition()
в соответствующих фрагментах.Каждый из этих методов принимает один параметр
Transition
предназначенный для выполнения анимации.Создавать анимацию мы будем очень просто. Мы используем наш кастомный transition для передвижения изображения (об этом чуть позже), и исчезание (
Fade
) при выходе.Классы анимации перехода
Android предоставляет некоторые готовые анимации переходов, что подходят для большинства случаев.
Fade
выполняет анимацию исчезновения. Slide
анимирует переход появления/исчезновения скольжением из угла экрана. Explode
анимация подобная взрыву, изображение движется от краев экрана. И наконец, AutoTransition
заставит изображение исчезать, двигаться и изменять размер. Это лишь некоторые примеры из пакета перемещений, их на самом деле намного больше!Я упоминал, что нам понадобится кастомный переход для нашего изображения. Вот он:
public class DetailsTransition extends TransitionSet {
public DetailsTransition() {
setOrdering(ORDERING_TOGETHER);
addTransition(new ChangeBounds()).
addTransition(new ChangeTransform()).
addTransition(new ChangeImageTransform()));
}
}
Наш кастомный переход есть ни что иное как набор из трех готовых переходов собранных вместе:
ChangeBounds
анимирует границы (положение и размер) нашей view.ChangeTransform
анимирует масштаб view, включая родителя.ChangeImageTransform
позволяет нам изменять размер (и/или тип масштаба) нашего изображения
Если вам интересно узнать, как они втроем взаимодействуют попробуйте поиграть с приложением, поочередно убирая то одну то другую анимации, наблюдая за тем как все ломается.
Вы так же можете создать более сложные анимации используя XML. Если вы предпочитаете XML, то вам будет интересно посмотреть документацию на сайте андроида
Transition
.Все вместе
Код который в итоге у нас получился оказался достаточно простым:
DetailsFragment details = DetailsFragment.newInstance();
// Note that we need the API version check here because the actual transition classes (e.g. Fade)
// are not in the support library and are only available in API 21+. The methods we are calling on the Fragment
// ARE available in the support library (though they don't do anything on API < 21)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
details.setSharedElementEnterTransition(new DetailsTransition());
details.setEnterTransition(new Fade());
setExitTransition(new Fade());
details.setSharedElementReturnTransition(new DetailsTransition());
}
getActivity().getSupportFragmentManager()
.beginTransaction()
.addSharedElement(holder.image, "sharedImage")
.replace(R.id.container, details)
.addToBackStack(null)
.commit();
Вот и все! Простой способ реализации анимации переходов между двумя фрагментами готов!
Комментарии (10)
Mishok2000
08.11.2015 22:49Честно говоря всегда бесила данная анимация в новом Андроиде. Она не имеет никакого реального смысла, так как мы понимаем, что в реальном мире та или иная карточка, или объект не может плавно появиться, или же испариться.
Тогда какую анимацию надо вставить? Я лично не знаю. Был бы очень рад услышать ответ на мой вопрос от профессиональных дизайнеров, да и вообще от кого угодно :)PapaBubaDiop
08.11.2015 23:54-2В Библии изложен сценарий анимации.
1. Сначала было слово. (Label)
…
Плюс 10 поправок от Диснея.
Lure_of_Chaos
09.11.2015 01:57Извините, но все просто: раньше была смена картинок мгновенно, которая обескураживала еще больше. Ныне резкую смену заменили плавной анимацией, что было воспринято как весьма приятное улучшение.
А в целом, если задуматься, проблема чисто психологическая, как кинематографа в целом — не мы обозреваем реальность в ожидании смены картины, а картина приходит к нам, изменчивая, как при наших действиях, без наших усилий.
А по существу — я бы рекомендовал использовать улучшенный эффект — не смену, а превращение картинки. и то, в более похожих картинках. было бы ближе к средневековому волшебству :)
gwer
09.11.2015 10:17Такая анимация крайне сомнительна для Material design. Все, что может происходить, описано в гайде от гугла. Куда логичнее будет рассматривать фото как карточку, которая сначала масштабируется вместе с фото, а затем растягивается отдельно (только фон), и уже на пустом ее месте отображается текст.
petrovichtim
09.11.2015 13:03Спасибо за статью. Сделал как написано, картинка перелетает, но вот обратно фрагмент растворяется.В чем может быть проблема?
withoutuniverse
Извините, но невозможно читать данный перевод. Исправьте и сделайте текст более дружелюбным для русскоговорящих людей.
AStefanovskiy
Подредактировал.