Анимации в Android по полочкам (Часть 2. Комплексные анимации)

    Часть 1. Базовые анимации
    Часть 2. Комплексные анимации
    Часть 3. «Низкоуровневые» анимации
    Часть 4. Анимации переходов
    Часть 5. Библиотеки для работы с анимацией

    Приведённые в предыдущей части инструменты были относительно низкоуровневыми и в Android есть куда более простые способы добиться красивых анимаций не прибегая к прямому рисованию графики или изменению свойств объектов.

    В этой части мы рассмотрим как можно минимумом усилий получить красивые анимации.

    Часть 2. Комплексные анимации


    1. Анимация изменений лэйаута (aka animateLayoutChanges)


    image

    Всё, что нам нужно сделать, чтобы добиться анимации как на гифке выше — это добавить флаг animateLayoutChanges в наш ViewGroup в xml. Теперь, когда мы удаляем или добавляем элемент в наш контейнер, либо изменяем его свойства, они автоматически будут анимированы.

    <AnyViewGroup
        ...
        android:animateLayoutChanges="true">
    

    Ладно, я немного слукавил когда говорил, что чтобы получить анимацию как на гифке выше, нужно всего лишь установить флаг. Добавление animateLayoutChanges на самом деле устанавливает LayoutTransition нашей ViewGroup. Но LayoutTransition по умолчанию анимирует только изменение видимости объектов в лэйауте. Поэтому если мы хотим изменять свойства объекта (например ширину и высоту) нужно включить эту опцию отдельно:

    val layoutTransition = viewGroup.layoutTransition
    layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
    

    Теперь точно всё. Если захочется как-то кастомизировать это поведение, то у LayoutTransition есть метод setAnimator позволяющий задать свою собственную анимацию изменений. Ну самые хардкорные ребята всегда могут написать свой LayoutTransition.

    • Применение:
    Базовая анимация изменений объектов на сцене.
    • Достоинства:
    Минимальные трудозатраты
    • Недостатки:
    Слабая кастомизация

    2. Transitions framework


    image

    Начиная с API 19 в Android появился новый фреймворк позволяющий создавать сложные анимации с участием большого количества элементов и минимумом кода.

    Есть два основных варианта его использования:

    1) Использование TransitionManager.beginDelayedTransition(ViewGroup)
    Чтобы создать анимацию необходимо перед внесением изменений в наши View вызвать TransitionManager.beginDelayedTransition(ViewGroup) и передать в него ViewGroup, который мы хотим анимировать. Фрэймворк запомнит состояние View и запустит анимацию на следующем кадре.

    TransitionManager.beginDelayedTransition(viewGroup)
    

    2) Создание сцен
    Создание анимации в этом случае сводится к созданию двух похожих xml, отвечающих за начальное и конечное состояние ваших анимаций. Соответственно, id объектов в xml должны совпадать, чтобы дать фреймворку возможность найти соответствие (На самом деле beginDelayedTransition тоже создаёт сцены, одну в момент вызова, а вторую на следующем кадре. После чего запускает анимацию между ними).

    var sceneA = Scene.getSceneForLayout(viewGroup, R.layout.scene_a, context)
    var sceneB = Scene.getSceneForLayout(viewGroup, R.layout.scene_b, context)
    private fun expand() {
        TransitionManager.go(sceneB)
    }
    private fun collapse() {
        TransitionManager.go(sceneA)
    }
    

    Кастомизация в Transitions framework достигается за счёт передачи объекта Transition вторым параметром. По умолчанию используется AutoTransition(), так что код ниже будет работать абсолютно так-же, как и код выше.

    TransitionManager.go(sceneA, AutoTransition())
    

    или

    TransitionManager.beginDelayedTransition(viewGroup, AutoTransition())
    

    И если заглянуть внутрь AutoTransition можно заметить что анимации будут происходить в последовательно в следующем порядке:
    — анимируются исчезающие объекты
    — анимируются изменения размеров
    — анимируются появляющиеся объекты

    setOrdering(ORDERING_SEQUENTIAL);
    addTransition(new Fade(Fade.OUT)).
    addTransition(new ChangeBounds()).
    addTransition(new Fade(Fade.IN));
    

    • Применение:
    Анимация большого количества объектов

    • Достоинства:
    Минимальные трудозатраты
    Доступная кастомизация

    Все примеры можно посмотреть и изучить здесь
    • +25
    • 5,5k
    • 4
    Поделиться публикацией
    Похожие публикации
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 4
    • +1
      Спасибо, что всё, действительно, по полочкам!
      Хотелось бы продолжения про игровую анимацию.
      • +1
        А можно пояснить что подразумевается под «игровой» анимацией?
        В следующуей части будет анимация при рисовании на канвасе, может быть это то что нужно. Но не могу точно сказать без конкретного кейса.
        Если игра написана на OpenGL, то это отдельная большая история.
        • +1
          отдельная большая история = отличная статья, где всё по полочкам ;)

          на самом деле мне, например, как новичку, очень интересно сравнение фрэймворков с OpenGL. Еще интересно сравнение производительности, удобства и прочего у канваса и OpenGL. Я прекрасно понимаю, что канвас далеко позади, но в определенных кейсах не хочется подключать большие либы к проекту.
      • +1
        Говоря о Transitions framework нельзя не упомянуть её бэкпорт для 4.X: transitions-everywhere. На хабрахабр есть даже статья от самого автора: habrahabr.ru/post/243363

        ЕМНИП бэкпорт Transitions framework недавно появился и в support-library.

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.