AnimatedVectorDrawable?

AnimatedVectorDrawable 클래스는 VectorDrawable, ObjectAnimator 또는 AnimatorSet과 함께 동작하는 애니메이션 효과 주는 클래스입니다
API25레벨 이전에는  UI 쓰레드에서 동작했던것과는 달리, API 25레벨부터는 RenderThread에서 동작합니다.
그래서 UI 쓰레드에 작업량이 많아도 동작이 매우 부드럽습니다.
UI쓰레드가 응답하지 않아도 UI쓰레드가 다음 프레임을 처리할수 있을 때까지 계속 애니메이션을 적용 할 수 있습니다.
따라서 RenderThread 가 활성된 AnimatedVectorDrawable과 UI 쓰레드 애니메이션을 정확하게 딱 조율하기는 힘듭니다.
추가적으로 렌더쓰레드에서 동작하는 AnimatedVectorDrawable이 마지막프레임이 끝나면 OnAnimationEnd(Drawable)이 호출됩니다.
 
For more details :
https://developer.android.com/reference/android/graphics/drawable/AnimatedVectorDrawable.html?hl=ko
 

녹화 버튼 중지 버튼 모핑 애니메이션 만들어 보기


 
 

path data 정의 하기

경로: res/values/paths.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="path_circle">M 2,6
        C 2,3.8 3.8,2 6,2
        C 8.2,2 10,3.8 10,6
        C 10,8.2 8.2,10 6,10
        C 3.8,10 2,8.2 2,6</string>
    <string name="path_rounded_rectangle">M 3,6
        C 3,3 3,3 6,3
        C 9,3 9,3 9,7
        C 9,9 9,9 7,9
        C 3,9 3,9 3,7</string>
</resources>

원과 모서리가 둥근 사각형을 벡터로 그리기 위한 path data 를 정의 해줍니다.
Note: 두개의 모양이 다른 쉐이프를 모핑을 하는 경우 path data의 종류나 갯수가 정확하게 일치해야만 합니다.
 

VectorDrawable 만들기

경로 : res/drawable/vector_record.xml

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:width="35dp"
    android:height="35dp"
    android:viewportHeight="12"
    android:viewportWidth="12">
    <group
        android:pivotX="6"
        android:pivotY="6">
        <path
            android:name="circle"
            android:fillColor="@color/red"
            android:pathData="@string/path_circle" />
    </group>
    <group
        android:pivotX="6"
        android:pivotY="6"
        android:scaleX="1.3"
        android:scaleY="1.3">
        <path
            android:name="outer"
            android:pathData="@string/path_circle"
            android:strokeColor="@android:color/black"
            android:strokeWidth="0.4" />
    </group>
</vector>

<vector>태그를 이용하여 VectorDrawable을 정의할 수 있습니다.
<group>태그는 패스들의 집합입니다. pivot이나 scale등의 속성을 설정을 할 수 있습니다.
<path>태그의 pathData 속성에 미리 정의 해둔 shape(원)의 id를 넣습니다.
ps: 저만 그런지 모르겠으나 pathData에 id로 참조하는 방식을 쓸경우 preview에 제대로 표현이 되지 않는 경우가 종종 보였습니다. 눈으로 보는게 중요하다면 path data를 직접 넣어주면 해결됩니다.
이제 완성된 xml을 이미지뷰에 넣으면 원형 녹화 버튼이 나오는것을 확인하실 수 있습니다. 하지만 아직 움직이지는 않습니다. 애니메이터를 추가 하지 않았으니까요.
둥근사각형 버튼 설명은 위 설명과 같으므로 생략하겠습니다.
 
AnimatedVectorDrawable 만들기
경로 : res/drawable/vector_record.xml

<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt"
    xmlns:tools="http://schemas.android.com/tools"
    android:drawable="@drawable/vector_record"
    tools:targetApi="lollipop">
    <target android:name="circle">
        <aapt:attr name="android:animation">
            <set
                android:fillAfter="true"
                android:ordering="together">
                <objectAnimator
                    android:interpolator="@android:anim/linear_interpolator"
                    android:propertyName="pathData"
                    android:valueFrom="@string/path_circle"
                    android:valueTo="@string/path_rounded_rectangle"
                    android:valueType="pathType" />
            </set>
        </aapt:attr>
    </target>
</animated-vector>

drawable-v21 폴더를 사용하지 않으므로 lint 에러가 날겁니다. lollipop이상에서만 쓸수 있기 때문이죠. drawable폴더를 반드시 사용하고 싶다면
targetApi 를 지정해줍니다.
drawable 속성에는 위에서 미리 정의한 vector drawable 리소스 id 를 넣습니다.
 
<target>태그에는 위에서 지정한 vectordrawable을에 대해 어떤 애니메이션을 지정할지 정하는 곳입니다.
애니메이터를 지정해야하는데 res/anim/애니메이션. xml 파일을 만들기 싫어 바로 선언해주었습니다.
fillafter속성은 애니메이션이 실행한 후 마지막 프레임상태로 유지할 것인지를 결정합니다.
ordering은 애니메이터가 여러개인경우 동시에 실행할것인지를 결정합니다. 동시면 together 한개씩이면 sequentially를 줍니다.
드디어 <objectAnimator>태그까지 왔습니다
interpolator에는 원하는 애니메이션 타입을 지정할 수 있습니다. 전 그냥 안드로이드 프레임워크에 들어가있는 linear interpolator 를 사용했습니다. 다양한 효과를 주고 싶다면 직접 정의 해서 사용하면 되겠죠?
valueFrom 에는 애니메이션이 시작할 path data를
valueTo에는 애니메이션이 끝날 path data를 넣어준뒤 나중에 애니메이션을 실행하면 자동으로 morphing이 됩니다.
 
거의 다왔습니다.
 
애니메이션 실행해보기
res/layout/activity_main.xml

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.oksisi213.animatedvectordrawablestudy.MainActivity">
    <ImageView
        android:id="@+id/record"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@drawable/anim_vector_record_to_stop"
        app:layout_constraintBottom_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

MainActivity.kt

class MainActivity : AppCompatActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_main)
      record.setOnClickListener {
         if (record.tag == null) {
            record.setImageResource(R.drawable.anim_vector_record_to_stop)
            (record.drawable as AnimatedVectorDrawable).start()
            record.tag = 0
         } else {
            record.setImageResource(R.drawable.anim_vector_stop_to_record)
            (record.drawable as AnimatedVectorDrawable).start()
            record.tag = null
         }
      }
   }
}

drawable객체를 AnimateVectorDrawable로 캐스팅하여 start()해주면 끝!
 
git : https://github.com/Charlezz/AnimatedVectorDrawableStudy.git
참고 : https://www.androiddesignpatterns.com/2016/11/introduction-to-icon-animation-techniques.html
 

Buy me a coffeeBuy me a coffee
카테고리: Android

1개의 댓글

이아무개 · 2018년 3월 29일 2:12 오후

퍼가요

답글 남기기

이메일은 공개되지 않습니다.