精确控制Androids VectorDrawable动画

Art*_*hur 20 android vector-graphics android-animation android-viewpager 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>
Run Code Online (Sandbox Code Playgroud)

动画矢量文件:

<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>
Run Code Online (Sandbox Code Playgroud)

用于运行动画的Java代码:

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

animated.start();
Run Code Online (Sandbox Code Playgroud)

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

Art*_*hur 12

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

一个经过一番研究,我结束了从复制以下类android.support.graphics.drawable包:AndroidResources,PathParser,TypedArrayUtils,VectorDrawableCommonVectorDrawableCompat.

接下来,我们需要做下面的方法和类公众的内部VectorDrawableCompat类:getTargetByName,VGroupVFullPath.

VectorDrawableCompat类中接下来删除检查Android版本(Build.VERSION.SDK_INT >= 23)的块.不知道为什么,但如果你不这样做,动画将不适用于Android API 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>
Run Code Online (Sandbox Code Playgroud)

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

ImageView myImageView;
VectorDrawableCompat.VGroup myVectorGroup;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_welcome);

    myImageView = (ImageView) findViewById(R.id.image_1);

    VectorDrawableCompat vectorDrawable = VectorDrawableCompat.create(getResources(), R.drawable.my_vector_drawable, null);
    vectorDrawable.setAllowCaching(false); // Important to allow image updates
    myVectorGroup = (VectorDrawableCompat.VGroup) vectorDrawable.getTargetByName("my_group");

    myImageView.setImageDrawable(vectorDrawable);

    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            if(myVectorGroup != null && position < 1) {
                myVectorGroup.setScaleX(1f - positionOffset);
                myVectorGroup.setScaleY(1f - positionOffset);

                myImageView.invalidate();
            }
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

我需要一些更多的测试来确定兼容性,但它现在适用!

  • 还没有试过这个,但很好的工作。很遗憾 AnimatedVectorDrawable 缺少这种开箱即用的功能。 (2认同)