精确控制Androids VectorDrawable动画

时间:2016-05-03 11:18:44

标签: android android-viewpager android-animation vector-graphics android-vectordrawable

更新:找到解决方案!向下滚动以查看我接受的答案!

我想为一个图像的多个元素设置动画并将动画链接到ViewPagers位置(因此多个元素会根据拖动的当前页面进行变形或飞入/滑出)。

那么,有没有办法精确控制动画的当前帧?例如,假设我有这个集合:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:interpolator="@android:anim/decelerate_interpolator"
        android:duration="800"
        android:propertyName="scaleY"
        android:valueFrom="0"
        android:valueTo="1" />
    <objectAnimator
        android:interpolator="@android:anim/decelerate_interpolator"
        android:duration="800"
        android:propertyName="scaleX"
        android:valueFrom="0"
        android:valueTo="1" />
    <objectAnimator
        android:interpolator="@android:anim/decelerate_interpolator"
        android:duration="800"
        android:propertyName="rotation"
        android:valueFrom="0"
        android:valueTo="360" />
</set>

动画矢量文件:

<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/pre_signup_1" >
    <target
        android:name="plus_button"
        android:animation="@anim/pre_signup_1_plus_container" />
    <target
        android:name="plus"
        android:animation="@anim/pre_signup_1_plus_sign" />
</animated-vector>

运行动画的Java代码:

ImageView mImage1 = (ImageView) findViewById(R.id.image_1);
AnimatedVectorDrawableCompat animated = (AnimatedVectorDrawableCompat) mImage1.getDrawable();

animated.start();

有没有办法像setCurrentDuration(400)一样控制动画,这可能会将动画的当前状态设置为一半?也许有一种方法可以将绘制的矢量分成多个层并以编程方式为它们设置动画?提前谢谢!

3 个答案:

答案 0 :(得分:9)

看起来可以访问VectorDrawableCompat内的路径和群组,并根据需要设置动画/变形!

经过一番研究后,我最终复制了android.support.graphics.drawable包中的以下类:AndroidResourcesPathParserTypedArrayUtilsVectorDrawableCommon和{{1 }}

接下来,我们需要在VectorDrawableCompat类内部公开以下方法和类:VectorDrawableCompatgetTargetByNameVGroup

接下来在VFullPath类中删除检查Android版本(VectorDrawableCompat)的块。不知道为什么,但是如果你不这样做,那么动画就不会在android API 23上起作用(需要更多的研究)。

我可能错过了几种私人方法,但如果你遇到问题,只需将它们公之于众。

所以,现在我们可以访问Build.VERSION.SDK_INT >= 23的图层了!以下是根据VectorDrawable位置缩放矢量组的小例子:

ViewPager

这是用于动画群组的代码:

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="276dp"
    android:height="359dp"
    android:viewportWidth="276"
    android:viewportHeight="359">

    <group
        android:pivotX="205.5"
        android:pivotY="214.5"
        android:name="my_group">
        <path
            android:strokeColor="#4D394B"
            android:strokeWidth="7"
            android:strokeLineJoin="bevel"
            android:fillColor="#1ED761"
            android:pathData="M206.5,180 C186.9,180,171,195.9,171,215.5 S186.9,251,206.5,251
C226.1,251,242,235.1,242,215.5 S226.1,180,206.5,180 Z" />
        <path
            android:fillColor="#4D394B"
            android:pathData="M210,211 L210,190 L202,190 L202,211 L181,211 L181,219 L202,219 L202,241 L210,241
L210,219 L232,219 L232,211 Z" />
    </group>
</vector>

我需要更多测试来确定兼容性,但它现在可以使用了!

答案 1 :(得分:2)

我认为你无法以编程方式使用 AnimatedVectorDrawable / AnimatedVectorDrawableCompat 执行此操作。

解决方法是使用Level List drawable并为其级别设置动画: 但是你需要大量的图像才能模拟平滑过渡,我在这里只用了三个级别进行演示。

首先,您将定义可绘制级别列表,如下所示: res / drawable / my_level_list.xml

<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/level0"
    android:maxLevel="0"/>
    <item android:drawable="@drawable/level1"
        android:maxLevel="1"/>

    <item android:drawable="@drawable/level2"
        android:maxLevel="2"/>
</level-list>

然后在布局文件中:

<ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:src="@drawable/my_level_list" />

然后在你的活动中:

int MIN_LEVEL=0;
int MAX_LEVEL=2;

ImageView img=(ImageView)findViewById(R.id.img);

Drawable myLevelSetDrawable= img.getDrawable();
ObjectAnimator anim=ObjectAnimator.ofInt(myLevelSetDrawable,"level",MIN_LEVEL,MAX_LEVEL);
anim.setInterpolator(new BounceInterpolator());
AnimatorSet set=new AnimatorSet();
set.play(anim);
set.setDuration(1000);
set.start();

希望有所帮助。

答案 2 :(得分:1)

就文档所说的AnimatedVectorDrawables而言,无法跟踪动画的状态或跳转到除animationStart和animationEnd之外的任何状态。

您可能必须使用自定义解决方案才能实现此效果。 This blog post解释了使用Android的窗口小部件状态跟踪来实现类似效果的方法。