AnimatedVectorDrawable的一些碎碎念

关于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,如作者所说:

  • VectAlign is based on an adaptation of the Needleman-Wunsch algorithm, which is used in bioinformatics to align protein or nucleotide sequences.

实测只要两个svg差异不是太大,效果还是相当不错的,该项目还拥有一个简单的可视化界面(命令行输入 java -jar vectalign.jar –gui 即可启动),他还会帮你将两个svg进行对齐,确定动画之后,还可以一键导出所需的xml文件,直接复制到项目中去使用。

你可能感兴趣的:(Android,Vector,兼容)