Android анимации. Часть 3. SVG, vector и управление анимацией

В прошлой статье мы увидели зачем нам Animator и как использовать анимации при смене состояний View. В этой статье мы посмотрим, как использовать анимации векторных картинок.

Простая анимация. Animator - первая статья
Простая анимация. State View - вторая статья
Vector анимация. Стандартные решения – третья статья
VectorDrawable анимация. Управление анимацией. Хардкор – четвертая статья

Я считаю, что это самые интересные анимации. При помощи небольших усилий мы можем добиться интересных эффектов. Изменения различных иконок, тот же hamburger превращающийся в стрелочку назад, реализованы именно так.
VectorDrawable состоит из Group и Path элементов. Анимацию мы создадим описав, как должны изменяться эти элементы.

Давайте разберем как превратить значок play в значок pause.

Для этого нам нужно нарисовать svg. Сделать это можно используя различные программы. Я использовал онлайн сервис – editor.method.ac. Чтобы красиво анимировать play в pause нам нужно разбить его на две части – верхний треугольник и нижний. Рисуем, сохраняем в svg и добавляем в наш проект при помощи Vector Assets.
Теперь у нас есть ic_play.xml:

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="20dp"
    android:height="20dp"
    android:viewportHeight="128"
    android:viewportWidth="128">

    <group
        android:name="group"
        android:pivotX="64"
        android:pivotY="64">

        <path
            android:name="pause1"
            android:fillColor="#000"
            android:pathData="M 44 32 L 44 64 L 100 64 L 100 64 Z"
            android:strokeColor="#000"
            android:strokeWidth="1" />
        <path
            android:name="pause2"
            android:fillColor="#000"
            android:pathData="M 44 96 L 44 64 L 100 64 L 100 64 Z"
            android:strokeColor="#000"
            android:strokeWidth="1" />
    </group>
</vector>

Обратите внимание, что мы задали pivotX и pivotY. Этим мы указали середину картинки для правильного поворота нашего изображения.

Дальше нужно создать несколько xml в package res/animator.
top_play_to_pause.xml

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:propertyName="pathData"
    android:valueFrom="M 44 32 L 44 64 L 100 64 L 100 64 Z"
    android:valueTo="M 32 40 L 32 56 L 96 56 L 96 40 Z"
    android:valueType="pathType" />

bottom_play_to_pause.xml

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:propertyName="pathData"
    android:valueFrom="M 44 96 L 44 64 L 100 64 L 100 64 Z"
    android:valueTo="M 32 88 L 32 72 L 96 72 L 96 88 Z"
    android:valueType="pathType" />

Обратите внимание, что мы здесь описали. Мы сказали, что один path (valueFrom скопирован из ic_play.xm) должен превратиться в другой. Где нам взять этот самый другой? Опять рисуем его в онлайн редакторе и добавляем в проект, чтобы получить VectorDrawable path который сможем вставить в valueTo. Как будет выглядеть наша трансформация? Мы можем очень удобно проверять это при помощи сервиса shapeshifter.design (если необходима будет помощь, пишите комментарии). Очень удобно в нем то, что он нам может выдать готовый xml, который останется лишь вставить в наш проект.

Также нам понадобится еще один xml в package res/animator - rotate_90.xml:

<objectAnimator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:propertyName="rotation"
    android:valueFrom="0"
    android:valueTo="90"
    android:valueType="floatType" />

Теперь нам нужно соединить это все воедино. Сделаем для этого xml в res/drawable - ic_play_to_pause.xml:

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_play">
    <target
        android:name="group"
        android:animation="@animator/rotate_90" />
    <target
        android:name="pause1"
        android:animation="@animator/top_play_to_pause" />
    <target
        android:name="pause2"
        android:animation="@animator/bottom_play_to_pause" />
</animated-vector>

Студия может ругаться на то, что animated-vector можно использовать только в API>21, но не обращайте на это внимание :) Что мы сделали здесь? Мы связали разные objectAnimator с разными частями нашего ic_play.xml по android:name.

Что дальше?
Идем в activity_main.xml и добавляем туда наш значок:

<android.support.v7.widget.AppCompatImageView
    …
    app:srcCompat="@drawable/ic_play_to_pause" />

Обратите внимание, что мы используем контрол из android support библиотеки, а также указываем drawable в app:srcCompat – все это позволит использовать animated-vector в проектах API >= 15.
Осталось лишь запустить анимацию. В коде пишем лишь одну строку:

((Animatable) imageView.getDrawable()).start();

В настройках проекта не забудьте поставить флаг

android {
    compileSdkVersion 26
    defaultConfig {
        ...
        vectorDrawables.useSupportLibrary = true
        }
    ...
}

Что мы получили в итоге? Смотрим результат ↓
ezgif.com-video-to-gif.gif

К сожалению, стандартными способами мы не можем управлять анимацией. Мы не можем привязать ее к какому-то событию, например, swipe, чтобы иконка менялась как тот же hamburger при открытии Navigation Drawer. Получается, что управлять vector animation нельзя? Не совсем так, но это уже совсем другая история.

androidjavaразработкаanimatorанимации
11
0 GOLOS
0
В избранное
MStorm
Заметки android разработки
11
0

Зарегистрируйтесь, чтобы проголосовать за пост или написать комментарий

Авторы получают вознаграждение, когда пользователи голосуют за их посты. Голосующие читатели также получают вознаграждение за свои голоса.

Зарегистрироваться
Комментарии (2)
Сортировать по:
Сначала старые