代码已经同步到GitHub
然后看一下效果图:
前两个图标是让android的组件使用VectorDrawable
后面的是动画效果 后面会详细介绍.
什么是VectorDrawable
VectorDrawable 是Android特有的SVG矢量图加载机制 这种机制将svg以xml文件解析出来 Path代表着一条线的路径
在AndroidStudio中创建一个VectorDrawable:
点进去之后的icon可以选择系统自带的 也可以选择右侧localfail 需要美工提供svg 或者去阿里矢量图扣
选择一个会生成一个xml文件 我选择的是朝下的箭头
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:pathData="M20,12l-1.41,-1.41L13,16.17V4h-2v12.17l-5.58,-5.59L4,12l8,8 8,-8z"
android:fillColor="#010101"/>
</vector>
这个path代表着vectorDrawable是如何在绘制这个路径
上面的width和height是宽高
viewportwidth 是将这个图片宽度虚拟的平分24份
path是路径的语法 毕竟我们图片都可以直接转换的 所以语法不需要进行深入的理解
如何加载VectorDrawable资源
因为谷歌是从5.0才开始支持VectorDrawable,那么如果是5.0以下的系统需要进行一些简单的配置才可以加载静态VectorDrawable资源
前提: gradle版本在1.2以上
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
然后我们要在加载这个布局的Activity中写一个静态代码块
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
配置完这两条之后我们就可以将ImaveView配置上矢量图资源文件了
<ImageView
android:layout_gravity="center_horizontal"
android:layout_width="35dp"
android:layout_height="40dp"
app:srcCompat="@drawable/ic_access_alarm_black_24dp"/>
那么这是静态的组件我们这样配置,如果是一个Button的话 我们这样配置是无效的
给Button配置矢量图资源我们需要通过selector来间接的完成~
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_access_alarm_black_24dp" android:state_pressed="true"/>
<item android:drawable="@drawable/ic_check_box_outline_blank_black_24dp" android:state_pressed="false"/>
</selector>
然后把这个selctor设置给button
<Button
android:layout_gravity="center_horizontal"
android:background="@drawable/bg_btn"
android:layout_width="50dp"
android:layout_height="50dp" />
好的 关于如何静态加载矢量图总结完了 下面讲解如何与属性动画一起实现效果
VectorDrawable与属性动画结合使用
首先我要强调一个特殊的情况,以我两个箭头左右摇摆的这个为例子(这个箭头是直接从系统素材库中生成)
如果我们直接生成的话 那么他的vector xml是:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M9.01,14L2,14v2h7.01v3L13,15l-3.99,-4v3z
M14.99,13v-3L22,10L22,8h-7.01L14.99,5L11,9l3.99,4z"/>
</vector>
path标签中的pathData 需要格外注意一下,因为我选择的这个矢量图 他是由两个完全分离开的部分组成,在代码中一个M代表一个部分,如果你删掉第二个M之后包裹第二个M的代码 那么右边的箭头在预览区中消失了
如果我们要控制这个VectorDrawable进行动画操作,那么我们需要调用group这个标签 我先展示一下
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<group
android:name="left">
<path
android:fillColor="#f88"
android:pathData="M9.01,14L2,14v2h7.01v3L13,15l-3.99,-4v3z"/>
</group>
<group
android:name="right">
<path
android:fillColor="#f88"
android:pathData="M14.99,13v-3L22,10L22,8h-7.01L14.99,5L11,9l3.99,4z">
</path>
</group>
</vector>
把每个M的部分用group标签包裹起来
group的name会对应我们等一下创建的粘合器文件中的属性
粘合器是什么?将VectorDrawable和objectAnimator属性动画进行连接
下面我们要创建两个objectAnimator文件 分别起名 anim_left anim_right
anim_left:
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/overshoot"
android:duration="1000"
android:repeatMode="reverse"
android:repeatCount="infinite"
android:propertyName="translateX"
android:valueFrom="0"
android:valueTo="10"
android:valueType="floatType">
</objectAnimator>
anim_right:
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/overshoot"
android:duration="1000"
android:repeatMode="reverse"
android:repeatCount="infinite"
android:propertyName="translateX"
android:valueFrom="0"
android:valueTo="-10"
android:valueType="floatType">
</objectAnimator>
我们创建了两个平移的属性动画 属性动画的具体属性我在上一篇文章中有总结
最后我们在drawable文件目录下来创建粘合器文件:
arrow_anim.xml:
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/arrow">
<target
android:name="left"
android:animation="@animator/anim_left" />
<target
android:name="right"
android:animation="@animator/anim_right" />
</animated-vector>
targe是要对应的属性动画文件 这回也对应上我上面写的group标签中的name属性了,这样属性动画和我们的VectorDrawable就一一对应上了
然后我们把这个粘合器设置到imageview上
<ImageView
android:id="@+id/anim"
android:layout_width="146dp"
android:layout_height="132dp"
app:srcCompat="@drawable/arrow_anim" />
下面是调用动画的java代码
Drawable drawable = imageView.getDrawable();
if (drawable instanceof Animatable) {
((Animatable) drawable).start();
}
下面总结trimPath与属性动画
trimPath与属性动画
下面我要用放大镜的这个例子总结这个点
首先还是先创建VectorDrawable的资源文件 并且根据M分割 (因为动画不同 所以不需要grop分组)
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="150dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="150">
<path
android:name="search"
android:pathData="M141,17 A9,9 0 1,1 142,16 L149,23"
android:strokeAlpha="0.8"
android:strokeColor="#000000"
android:strokeLineCap="round"/>
<path
android:name="bar"
android:pathData="M0,23 L149,23"
android:strokeAlpha="0.8"
android:strokeColor="#000000"
android:strokeLineCap="square"
android:strokeWidth="2"/>
</vector>
然后我们创建两个objectAnimator文件在animator目录下
anim_search.xml 放大镜动画:
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:propertyName="trimPathStart"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType">
</objectAnimator>
anim_bar横线动画:
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:propertyName="trimPathStart"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType">
</objectAnimator>
其实这两个是一样的 但是他们俩如何实现动画的呢
android:propertyName="trimPathStart"
这个属性起到了关键
配合下面两个属性一起就是开始的时候 我的path长度是0 慢慢在3秒内到了1的长度也就是百分之百 不知道体会到了没有
下面还是老套路 粘合器跟第一个例子是一样我就不贴了源码里面都有
然后我们用想通java代码调用及可 下面介绍第三个例子
PathData与属性动画
如果我们想要把五角星硬生生的变成六边形,那么我们就可以修改属性动画文件中的属性就可以达到(后面会强调关于他的兼容性问题)
首先还是老套路 先找一个五角星的VectorDrawablexml文件设置给imageview作为默认图片
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="120dp"
android:height="120dp"
android:viewportHeight="64"
android:viewportWidth="64">
<path
android:name="star"
android:fillColor="#22e171"
android:pathData="M 48,54 L 31,42 15,54 21,35 6,23 25,23 32,4 40,23 58,23 42,35 z"
android:strokeColor="#000000"
android:strokeWidth="1"/>
</vector>
我们新建一个anim_fivestar.xml在animator目录下
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:propertyName="pathData"
android:valueFrom="M 48,54 L 31,42 15,54 21,35 6,23 25,23 32,4 40,23 58,23 42,35 z"
android:valueTo="M 48,54 L 31,54 15,54 10,35 6,23 25,10 32,4 40,10 58,23 54,35 z"
android:valueType="pathType">
</objectAnimator>
第一个path是五角星的path 第二个path是六边形的path 相信大家都看明白是怎么回事了
然后再配置连接器
下面就是如何调用这个动画了
首先这个pathData直接改变的动画目前谷歌是不支持5.0以下的手机的 所以使用这总方式实现炫酷动画的小伙伴们一定要慎用啊
判断完手机系统版本后 我们就调用下面的java代码开始动画
fivestart = (ImageView) findViewById(R.id.fivestart);
AnimatedVectorDrawable drawable= (AnimatedVectorDrawable) getDrawable(R.drawable.fivestart_anim);
fivestart.setImageDrawable(drawable);
if (drawable != null){
drawable.start();
}
发生了一点点小变化 也就是我们要直接得到粘合器的drawable对象并强转为AnimatedVectorDrawable类型
然后我们再给iamgeview通话java代码进行设置并开始
但是及时是通过java代码动态设置
相应的组件xml上也别忘了设置这个app属性
<ImageView
android:id="@+id/fivestart"
app:srcCompat="@drawable/fivestart_anim"
android:layout_width="100dp"
android:layout_height="100dp" />