Pull to refresh

Работа с анимацией. AnimatedVectorDrawableCompat

Reading time 4 min
Views 6K
В этой стате хотел бы всем рассказать и показать на практике, как можно делать анимацию в Android приложении при помощи AnimatedVectorDrawableCompat, например свои кастомные кнопки, ImageView, FloatingActionButton.



На сегодняшний день информации по этому поводу в сети не так много, точней ее совсем — нет. Все, что мне удалось найти — это недавние представленные новшества Google, а именно:

Статья из Android Developer Blog
Видео с Google I/O 2016
Android Reference

Этого по сути мало, чтобы понять, как применить на практике AnimatedVectorDrawableCompat.

Теперь непосредственно перейдем к применению.

На первом этапе нам нужно избавиться от того, чтоб фреймворк превращал иконку в .png. С версии 23.3.0 можно использовать .xml и для это нужно в Gradle app level добавить следующий flag:

android {
    ...

    defaultConfig {
       ...
        vectorDrawables.useSupportLibrary = true
    }

}


И в зависимость подключить последнюю версию AppComapt:

dependencies {
    ...
    compile 'com.android.support:appcompat-v7:23.4.0'
}


Далее, в примере я буду использовать квадрат (синий), который будет немного накрывать своими углами круг (красный).
На выходе мы должны задействовать 2 объекта и заставить их непрерывно двигаться соответственно по оси X (квадрат) и Y (круг).

Шаги:

1)

Создаем Drawable Resource File, называем файл — icon.xml и кладем в папку drawable:

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

   <group
       android:name="circle"
       android:scaleX=".7"
       android:scaleY=".7"
       android:pivotX="12"
       android:pivotY="12">
       <path
           android:fillColor="#ff0000 "
           android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2z"/>
   </group>

   <group
       android:name="square"
       android:scaleX="1"
       android:scaleY="1"
       android:pivotX="12"
       android:pivotY="12">

       <path
           android:fillColor="#FF0000ff"
           android:pathData="M6,6h12v12H6z"/>
   </group>
</vector>


2)

Для хранения анимации в своем проекте мы создаем папку animator — res/animator
В нее мы положим два объекта и назовем их соответственно:

a) circle.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:propertyName="translateX"
        android:valueType="floatType"
        android:valueFrom="0"
        android:valueTo="5"
        android:repeatMode="reverse"
        android:repeatCount="infinite"
        android:duration="250" />
</set>


b) square.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:propertyName="translateY"
        android:valueType="floatType"
        android:valueFrom="0"
        android:valueTo="5"
        android:repeatMode="reverse"
        android:repeatCount="infinite"
        android:duration="250" />
</set>


Здесь же мы и указали, что объекты будут двигать по оси X и Y, откуда будут начинать движение, а также бесконечность движений.

Если у вас больше именованных групп, которые нужно анимировать — то вот в этой директории их и нужно создавать, соответсвенно и больше групп будут в основном файле — icon.xml

3)

Теперь создаем непосредственно анимированный файл, на который будем ссылаться в layout или в коде — res/drawable/anim_icon:

<?xml version="1.0" encoding="utf-8"?>
<animated-vector 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/icon">

   <target
       android:name="square"
       android:animation="@animator/square" />

   <target
       android:name="circle"
       android:animation="@animator/circle" />

</animated-vector>


Примечание: Android Studio подчёркивает красным animated-vector (если мин.версия проекта меньше 21), но если вы подключили flag, как указанно в начале — все заработает.

4)

Теперь мы можем обращаться к анимированным векторам в xml. Это может быть — ImageView, ImageButton, FloatingActinonButton:

<LinearLayout
     ...
     xmlns:app="http://schemas.android.com/apk/res-auto"/>

    <ImageView 
        app:srcCompat="@drawable/anim_icon"
	
        ... />

</LinearLayout>


5)

Обращаемся из кода к векторам. Здесь я также повесил OnClickListener и сохранил состояние при перевороте:

static final String STATE_ANIM = "isAnim";

    boolean mIsAnim;
    AnimatedVectorDrawableCompat avd;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        ImageView imageView = (ImageView) findViewById(R.id.imageView);
        if (imageView != null) {
            Drawable drawable = imageView.getDrawable();
            avd = (AnimatedVectorDrawableCompat) drawable;

            if (savedInstanceState != null) {
                mIsAnim = savedInstanceState.getBoolean(STATE_ANIM);
                if (mIsAnim) {
                    avd.start();
                }
            }

            imageView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                        if (avd.isRunning()) {
                            avd.stop();
                            mIsAnim = false;
                        }
                        avd.start();
                        mIsAnim = true;
                }
            });
        }
        
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean(STATE_ANIM, mIsAnim);
    }
}


Примечание: не забудьте подтянуть зависимость:

import android.support.graphics.drawable.AnimatedVectorDrawableCompat;


Результат проделанной работы:



P.S

Недавно появилась возможность объединить файлы my_vector.xml и anim_vector в одном anim_vector (теперь отдельный файл res/drawable/my_vector.xml не нужен), а также добавить сюда и файлы-аниматоры (objectAnimator) таким образом получится один файл на всю анимацию.

Представили это Google на I/O, но к сожалению — не работает. На видео с 14 минуты говориться об этом.
Tags:
Hubs:
+3
Comments 4
Comments Comments 4

Articles