关于Vector及AnimatedVectorDrawable的一些基本知识,请参见徐医生的Android Vector曲折的兼容之路 ,写的很全,很棒。
读完上文之后,我们对静态的vector和动态的AnimatedVectorDrawable有了一定的了解,并做了一些小的尝试,本文里边主要说的是一些兼容性的问题及解决方案。
从AppCompat23.2开始,Google开始支持在低版本上使用Vector,兼容性还是相当不错的,但是动态的AnimatedVectorDrawable在低版本的兼容上边问题就很大了,除了目前不能在L之下的版本上使用以外,还有一些其他的坑。
AnimatedVectorDrawableCompat animatedVectorDrawable = (AnimatedVectorDrawableCompat) getResources().getDrawable(R.drawable.vectalign_animated_vector_drawable_start_to_end);
ImageView imageView = (ImageView) findViewById(R.id.image_svg);
imageView.setImageDrawable(animatedVectorDrawable);
animatedVectorDrawable.start();
上述代码可以让我们在Android L以上去播放一个AnimatedVectorDrawable,但在低版本上xml中的标签animated-vector会报错:org.xmlpull.v1.XmlPullParserException: Binary XML file line #1: invalid drawable tag animated-vector
即使用上了AnimatedVectorDrawableCompat也无效,所以如果不用三方库(后边会说),只能将其分开两种版本来写:API21以上用动画,API21之下用静态的SVG图片。
除了版本兼容的问题之外,你可能还会发现animatedVectorDrawable没有可以对动画做监听的方法,没法让我们在动画结束之后去做一些事情,比如去重新播放一遍动画。翻遍了animatedVectorDrawable的所有方法,发现了一个看起来比较像的方法:
animatedVectorDrawable.registerAnimationCallback(new Animatable2.AnimationCallback() {
@Override
public void onAnimationStart(Drawable drawable) {
super.onAnimationStart(drawable);
}
@Override
public void onAnimationEnd(Drawable drawable) {
super.onAnimationEnd(drawable);
animatedVectorDrawable.start();
}
});
看起来没什么问题,但是在L版本上边代码居然崩溃了,后来google之后,发现这个方法只有在6.0以上才是正常使用的,之前版本都会有问题。同时大家对监听AnimatedVectorDrawables的结束提供了一些意见,参考:
Is there a way to listen for animation end in AnimatedVectorDrawables
How to restart android AnimatedVectorDrawables animations?
以上是使用官方方法的一些问题,但是我们为了兼容低版本,还是得使用一些三方库来进行兼容,比如:vector-compat ,github上边有接入的方法,很简单,唯一比较麻烦的就是好多属性得设置两次,另外需要注意的是,他主页加入文档中并没有说明,在两个vector图像里边还有两个动画里边都有需要添加的自定义属性:
动画中需要添加 app:vc_valueType=”pathType”这个属性
<set xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<objectAnimator
android:duration="1500"
android:propertyName="pathData"
android:valueFrom="xxx"
android:valueTo="xxx"
android:valueType="pathType"
app:vc_valueType="pathType"
/>
set>
vector中需要添加 app:vc_viewportWidth=”313” app:vc_viewportHeight=”313” app:vc_fillColor=”#6666ff” app:vc_pathData=”xxx” 这四个属性
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:height="300dp"
android:width="300dp"
android:viewportHeight="313"
android:viewportWidth="313"
app:vc_viewportWidth="313"
app:vc_viewportHeight="313"
>
<path
android:name="v"
android:strokeColor="#ffff33"
android:strokeWidth="1"
android:fillColor="#6666ff"
android:pathData="xxx"
app:vc_fillColor="#6666ff"
app:vc_pathData="xxx"
/>
vector>
同时,因为该三方中默认提供的是按钮,并且也没有对动画状态的监听过程,所以需要监听动画结束的还是要参照上边给出的方案。
另外,如果你有两张形状不同的比较复杂的svg,想要做一个两者之间的转换动画,可以使用vectalign,如作者所说:
实测只要两个svg差异不是太大,效果还是相当不错的,该项目还拥有一个简单的可视化界面(命令行输入 java -jar vectalign.jar –gui 即可启动),他还会帮你将两个svg进行对齐,确定动画之后,还可以一键导出所需的xml文件,直接复制到项目中去使用。