Android Transitions: на сцену выходит Scene.

Что такое Scene?

Artem Shevchenko
5 min readApr 28, 2018

По документации Scene это набор значений параметров View которые применятся к иерархии View когда сцена будет использована.

Изучив документацию и исходный код этого класса, я дал от себя такое определение: Scene это инкапсуляция изменения View, изменяет содержимое View два раза — при применении этой Scene и при отмене. Звучит многообещающе и сложно, а на самом деле это очень простой класс, поэтому предлагаю рассмотреть этот класс подробнее и на интересных примерах.

Вероятно самый простой, и наверное лучший, способ понять и изучить какую-то технологию, особенно в мире программирования, это попробовать эту самую технологию на деле. Давайте попробуем при помощи Scene сделать вот такой анимированный переход:

Как мы будем это делать:

  • Определимся с основными терминами и понятиями
  • Потом мы создадим разметку для rootView и contentView
  • Затем мы сделаем Scene для нашей rootView и передадим туда contentView
  • А затем запустим все это и… Поехали!

Основные термины и определения

Сперва давайте разберем основные понятия и термины:

rootView — это ViewGroup внутри которого Scene будет делать изменения при применении и отмены этой Scene.

contentView — это View, которую наша Scene установит в rootView. Это может быть просто xml-разметка, либо объект View; впрочем можно обойтись и без этого, а сделать манипуляции в rootView вручную используя mEnterAction:

Пример: что можно делать при помощи enter/exit-Action()

В этом примере в rootView находится View logoLayout. В методах Scene setEnterAction(..) и setExitAction(..) мы передаем объект Runnable, и при вызове методов enter()/exit() Scene запустит указанное нами действие. Интересно, что никаких проверок типа “а изменяете ли вы что-то в rootView при вызове enter/exit-Action” нет, и вы можете делать внутри метода run() что угодно.

Применение и отмена Scene — у класса Scene есть два основных метода для изменения rootView: enter() и exit(). Внутри enter() к rootView применяется contentView и вызывается mEnterAction, это применение Scene, а при вызове метода exit() у нас есть возможность сделать что-то с rootView только при помощи mExitAction и это отмена Scene. Хочу отметить что эти термины не встречаются в документации (а зря), и я использую их в этой статье для удобства понимания материала.

Давайте сделаем rootView и contentView

rootView:

Наш rootView в этом примере — это CardView, который обеспечит округлые края и тень

В качестве rootView может быть любой объект класса ViewGroup. Для работы со Scene rootView нужен обязательно.

contentView:

Scene content — чтоб фон с морем сохранил пропорции делаем это через ImageVIew

Теперь у нас есть rootView и contentView и мы можем опробовать Scene в действии!

Применение Scene

Давайте перед стартом освежим теорию: берем Scene, указываем где будем делать изменения (rootView), как будем изменять (contentView + mEnterAction) и, собственно, применяем нашу Scene — метод enter(). Вперед, к практике!

Создаем Scene, где cardView это наш rootView, для contentView мы берем файл с xml-разметкой.

Давайте посмотрим что у нас получилось на экране телефона:

Хм, а где анимация?

— Хм, если проскролить статью наверх то там на gif-ке совсем другая картинка, поприятнее будет, автор ты чо людей вводишь в заблуждение? — скажете вы…

TransitionManager! — отвечу я вам.

Анимация применения Scene

Для анимации нашей Scene нам понадобится TransitionManager и вот почему: Scene, как говорилось в самом начале статьи, служит для инкапсуляции изменения нашей View, а для анимации есть специальные отдельные классы — Transition’s, которые знают как анимировать изменения которые делает Scene.

Иными словами Scene знает как изменить, а Transition’s знают как анимировать эти изменения. Scene изменяет View, а Transition’s анимируют. Сами Transition’s и TransitionManager мы детально рассмотрим в другой статье, так как это тема довольно большая и лучше разобрать её отдельно, а сейчас давайте все таки попробуем TransitionManager:

Та-же Scene, но применять её будем через TransitionManager

Давайте запустим, посмотрим что получилось, а потом разберемся куда пропал enter() и что это за метод go(). Обратите внимание что Scene точно такая как в предыдущем примере, и единственное что поменялось это вместо метода enter() у Scene мы вызываем метод go() у TransiotionManager-а.

Появление уже более плавное, но все равно это не то

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

Анимация по умолчанию

Вызывая метод go() мы передаем туда нашу Scene. Поскольку мы не указываем явно какой Transition использовать при применении нашей Scene, TransitionManager применяет свою дефолтную анимацию при помощи AutoTransition. Этот класс по сути набор из нескольких базовых Transition-ов, которые анимируют появление и исчезновение View’s внутри rootView, а так-же изменение размеров и положения View’s на экране.

В самом начале наша rootView была пустая, просто белая CardView и поэтому при применении нашей Scene TransitionManager просто показывает наш contentView — хоть и плавно, но все равно не так как мы этого хотим. Поэтому нам нужно определить вручную как анимировать изменения при применении Scene и использовать это вместо дефолтного AutoTransition.

Собственная анимация

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

Красота требует жертв, а красивая анимация требует увеличения количества строк кода — ведь для того, чтоб анимация была именно такая, как вы задумали, её придется определить вручную для каждого элемента. Конкретно для нашего примера мы укажем для картинки с морем плавное появление, а для текста — плавный подъезд. Все эти анимации мы объединяем в один TransitionSet и давайте еще явно укажем время анимации — 1 секунду.

Давайте запустим наш код и посмотрим что получилось! Заметьте, что мы все еще используем ту же самую Scene что и в предыдущих примерах и используем тот же метод go(), правда теперь передавая туда свою собственную анимацию. Итак — смотрим на экран…

Да! Это то что нам нужно! Наконец то!

Наконец получилось! Работая с Transition’s запомните эти слова — когда у вас все будет двигаться на экране так, как вы задумали, вы будете очень рады, так как при работе с Transition’s всплывает множество неочевидных вещей и придется попотеть!

Заключение

Мы разобрали базовый класс Scene, разобрали основные понятия и базовые методы Scene, как его использовать и зачем он нужен. Более того — мы познакомились с Transition’s и с TransitionManager и разобрали на простом примере как этим всем пользоваться.

Я сделал проект с примерами и обзором Transition API для анимированных переходов между экранами — думаю вам это пригодится! Буду рад вашим лайкам, форкам и комментариям!

Дополнительная информация:

Метод enter() более подробно:

Scene.enter()

--

--