Pull to refresh

Анимация переходов между двумя фрагментами

Reading time 4 min
Views 26K
Original author: Bryan Herbst
image Одним из краеугольных камней в Material design являются осмысленные движения между экранами. Lollipop предоставляет поддержку этих анимаций в форме фреймворка переходов между Activity и Fragment. Поскольку статей по данной теме не так много, я решил написать свою собственную!

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

Если вы желаете увидеть, что получилось — готовое приложение находится на 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();

Вот и все! Простой способ реализации анимации переходов между двумя фрагментами готов!
Tags:
Hubs:
+19
Comments 10
Comments Comments 10

Articles