咱们在平常使用各类app的时候,会发现原来越多下面这类型的矢量图标动画。图标动画是material design所推荐的图标效果。固然对我来讲,炫酷的效果就是我学习矢量图标动画的一个很充分理由。 html
了解一些svg指令,知道矢量图是怎么画出来的,对咱们之后的开发有好处,咱们能够从一个简单的VecotrDrawable文件入手。android
<?xml version="1.0" encoding="utf-8"?>
<!--res/drawable/vd_check.xml-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="100dp"
android:height="100dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:name="check"
android:pathData="M4,10 L9,16 L20,4"
android:strokeColor="#35931d"
android:strokeWidth="3" />
</vector>
复制代码
这个绿色和谐的小勾是我用上面的vd_check文件画出来的,咱们来解读下这个文件:git
关键字 | 解释 |
---|---|
M x,y | 把画笔移动到从(x,y)这个点。通常表明着一段path的开始。 |
L x,y | 画一条链接到(x,y)的线段。 |
Q x1,y1 x,y | 贝塞尔二阶曲线。通过(x1,y1)到达(x,y)。 |
C x1,y1 x2,y2 x,y | 贝赛尔三阶线。通过(x1,y1)和(x2,y2)到达(x,y)。 |
Z | 闭合path。画一段到起点的线段。 |
如今回过头看和谐小勾的pathData,就很简单了:github
M4,10 L9,16 L20,4bash
从(4,10)开始,画一条到(9,16)的线段,再画一条到(20,4)的线段。一顿一拉,绿色小勾跃然纸上。app
固然,若是遇到比小勾更加复杂的状况,好比一个完美的心形,或者广州塔的图标,那仍是乖乖的找ui帮你生成svg比较好。svg
既然咱们有了矢量图,那就让矢量图动起来吧。提及作动画,固然是属性动画来一发啦!学习
<?xml version="1.0" encoding="utf-8"?><!--vd_check.xml-->
<!--vd_check.xml-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="100dp"
android:height="100dp"
android:viewportHeight="24"
android:viewportWidth="24">
<group
android:name="g_rotation"
android:pivotX="12"
android:pivotY="12"
android:rotation="0">
<path
android:name="check"
android:pathData="M4,10 L9,16 L20,4"
android:strokeAlpha="1.0"
android:strokeColor="@color/colorPrimary"
android:strokeLineCap="round"
android:strokeWidth="1" />
</group>
</vector>
复制代码
咱们要加什么动画呢?嗯、、旋转,透明度,颜色,我全都要!动画
<?xml version="1.0" encoding="utf-8"?>
<!--/res/animator/rotation_round.xml-->
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360" />
复制代码
<?xml version="1.0" encoding="utf-8"?>
<!--/res/animator/alpha_animator.xml-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="sequentially">
<objectAnimator
android:duration="500"
android:propertyName="strokeAlpha"
android:valueFrom="1f"
android:valueTo="0f" />
<objectAnimator
android:duration="500"
android:propertyName="strokeAlpha"
android:valueFrom="0f"
android:valueTo="1f" />
</set>
复制代码
<?xml version="1.0" encoding="utf-8"?>
<!--res/animator/stroke_color_animator.xml-->
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="strokeColor"
android:valueFrom="@color/colorPrimary"
android:valueTo="@color/colorAccent"
android:duration="1000"/>
复制代码
AnimatedVector华丽登场,把vector和动画文件黏合在一块儿。使用起来很简单,先经过drawable属性指定vector,而后经过target标签把动画和对象绑定在一块儿。ui
<?xml version="1.0" encoding="utf-8"?>
<!--avd_check.xml-->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/vd__check">
<target
android:name="g_rotation"
android:animation="@animator/rotation_around" />
<target
android:name="check"
android:animation="@animator/stroke_color_animator" />
<target
android:name="check"
android:animation="@animator/alpha_animator" />
</animated-vector>
复制代码
最后须要在代码中触发。把avd_check.xml当作图片赋给ImageView,须要调用动画时,获得ImageView的drawable,强转为Animatable后,调用start()方法。
<ImageView
android:id="@+id/img_check"
android:layout_width="48dp"
android:layout_height="48dp"
app:srcCompat="@drawable/avd_check" />
复制代码
··· img_check.setOnClickListener { val drawable = img_check.drawable (drawable as Animatable).start() } ···
而后效果就出来了。
固然,若是你只是求方便的话,动画不须要单独写一个文件,直接写在target标签里面也是能够的。
trimPath其实和上面的动画如出一辙,只是运用了几个矢量图标特有的属性而已。咱们先来看看trimPath能作什么。
trimPath一共有三个相关的属性:trimPathStart,trimPathEnd,trimPathOffset,都是float类型的数值,数值范围从0到1。分别表示path从哪里开始,到哪里结束,距离起点多远。至于怎么用,就看咱们的想象力了。
接下来,用咱们的小勾来作下实验吧。
照旧也是须要写一个动画文件
<?xml version="1.0" encoding="utf-8"?>
<!--trim_path_animator.xml-->
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:interpolator="@android:interpolator/linear"
android:propertyName="trimPathEnd"
android:valueFrom="0.0"
android:valueTo="1.0"
android:valueType="floatType" />
复制代码
修改一下animatedVector文件
<?xml version="1.0" encoding="utf-8"?><!--avd_check.xml-->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/vd__check">
<target
android:name="check"
android:animation="@animator/trim_path_animator" />
</animated-vector>
复制代码
bang!
ps:pathTrim只能对一条完整的path作动画,若是你的pathdata是有断开的,好比(省略坐标):“M,L,L M,L Z”,出现了两个m,那path就会分红了两段,这时候pathTrim只会做用于第一条线段了。
重头戏来了,path变幻。咱们想想,既然strokeAplha,rotation这些属性都能作动画,那pathData这个属性,确定也能作动画啦。因而有了下面这些效果。
简单来讲就是给属性动画里面的valueFrom和valueTo分别写两条不同的path,那path就会自动变幻了。 须要注意的是,两条path的绘制指令须要在数量和结构上都相同。好比第一条path的指令(省略了坐标)是"M,L,L,C,Z",那第二条path的指令也应该是"M,L,L,C,Z"这种形式。
好,咱们能够来试一试手。因为如今的勾的指令太少了,很差发挥个人小宇宙,因此我多加了几个指令。而目标,就是把小勾变成小圆圈吧。因而乎我就创造了如下两条path。他们都用了一个m指令和4个c指令(是的,c只能也能画直线的)。 为了方便管理,我把这两个path都放在一个xml里面了。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="check_path">M4,10 C10,16 10,16 10,16 C13,13 13,13 13,13 C16,10 16,10 16,10 C20,6 20,6 20,6</string>
<string name="circle_path">M4,12 C4,7.6 7.6,4 12,4 C16.4,4 20,7.6 20,12 C20,16.4 16.4,20 12,20 C 7.6,20 4,16.4 4,12</string>
</resources>
复制代码
而后也是动画和animatedVector:
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:interpolator="@android:interpolator/linear"
android:propertyName="pathData"
android:valueFrom="@string/check_path"
android:valueTo="@string/circle_path"
android:valueType="pathType" />
复制代码
<?xml version="1.0" encoding="utf-8"?><!--avd_check.xml-->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/vd__check">
<target
android:name="check"
android:animation="@animator/path_animator" />
</animated-vector>
复制代码
接下来,噔噔噔噔噔。
可是你会发现,个人勾变成圆以后,再也变不回来了,动画不能倒过来作。因而乎咱们须要引入最后一个概念,animatedSelecotr。
animated-selector容许定义有多个vector,根据不一样状态使用不一样的vector,而且经过animated-vector定义不一样vector以前切换的动画。 因此咱们接下来的步骤是:
动手动手: 圆的vector文件。和勾的大同小异。注意,我把name改为了circle。
<?xml version="1.0" encoding="utf-8"?><!--vd_circle.xml-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="100dp"
android:height="100dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:name="circle"
android:pathData="@string/circle_path"
android:strokeAlpha="1.0"
android:strokeColor="@color/colorPrimary"
android:strokeLineCap="round"
android:strokeWidth="1" />
</vector>
复制代码
圆和勾的相互转化,须要两个文件。因为勾转化为圆已经在上面写过了(avd_check.xml,为了改名副其实,已经更名为avd_check2circl.xml)。这里是圆转化为勾。能够看到,动画是能够直接写在animated-vector里面的。
<?xml version="1.0" encoding="utf-8"?>
<!--huan -->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:drawable="@drawable/vd_circle">
<target android:name="circle">
<aapt:attr name="android:animation">
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="pathData"
android:valueFrom="@string/circle_path"
android:valueTo="@string/check_path"
android:valueType="pathType" />
</aapt:attr>
</target>
</animated-vector>
复制代码
接下来就剩下animated-selector了。
<?xml version="1.0" encoding="utf-8"?>
<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/check"
android:drawable="@drawable/vd__check"
android:state_checked="true" />
<item
android:id="@+id/circle"
android:drawable="@drawable/vd_circle"
android:state_checked="false" />
<transition
android:drawable="@drawable/avd_check2circle"
android:fromId="@id/check"
android:toId="@id/circle" />
<transition
android:drawable="@drawable/avd_circle2check"
android:fromId="@id/circle"
android:toId="@id/check" />
</animated-selector>
复制代码
使用的时候须要放在app:srcCompat里面。
<ImageView
android:id="@+id/img_check_selector"
android:layout_width="48dp"
android:layout_height="48dp"
app:srcCompat="@drawable/asl_check" />
复制代码
而后再代码中经过setImageState方法设置不一样的状态,图标就会自行变化了。
img_check_selector.setOnClickListener {
isCheckSelect = !isCheckSelect
img_check_selector.setImageState(intArrayOf(if (isCheckSelect) android.R.attr.state_checked else -android.R.attr.state_checked), true)
}
复制代码
srcCompat是专门针对vector drawable的,因此最好仍是使用srcCompat代替android:src。
到这里,咱们能够看到矢量图标动画的强大之处,无视马赛克,充满想象力,让咱们的app更生动,更符合Material Design。可是也有vector Drawable的生成麻烦,编写各类animated-selector,animated-vector文件繁琐等缺点。只能说有得就有失了。
与其感慨路难行,不如立刻出发。
*最后的最后,感谢你们的阅读,欢迎留言。 *