Уважаемые пользователи Голос!
Сайт доступен в режиме «чтение» до сентября 2020 года. Операции с токенами Golos, Cyber можно проводить, используя альтернативные клиенты или через эксплорер Cyberway. Подробности здесь: https://golos.io/@goloscore/operacii-s-tokenami-golos-cyber-1594822432061
С уважением, команда “Голос”
GOLOS
RU
EN
UA
mstorm
7 лет назад

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 нельзя? Не совсем так, но это уже совсем другая история.

71
0.000 GOLOS
На Golos с February 2018
Комментарии (2)
Сортировать по:
Сначала старые