android - 精确控制 Android 的 VectorDrawable 动画

标签 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) 这样控制动画,它可能会将动画的当前状态设置为一半?也许有一种方法可以将该矢量可绘制对象拆分为图层并以编程方式对其进行动画处理?提前致谢!

最佳答案

看起来可以访问 VectorDrawableCompat 中的路径和组,并根据需要对它们进行动画/变形!

经过一番研究,我最终从 android.support.graphics.drawable 包中复制了以下类:AndroidResourcesPathParserTypedArrayUtilsVectorDrawableCommonVectorDrawableCompat

接下来,我们需要在 VectorDrawableCompat 类中公开以下方法和类:getTargetByNameVGroupVFullPath

接下来在 VectorDrawableCompat 类中移除检查 Android 版本 (Build.VERSION.SDK_INT >= 23) 的 block 。不知道为什么,但如果你不这样做,动画将无法在 android API 23 及更高版本上运行(需要更多研究)。

我可能遗漏了一些私有(private)方法,但如果遇到问题,只需将它们公开即可。

所以,现在我们可以访问 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>

这是用于动画组的代码:

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();
            }
        }
    });
}

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

关于android - 精确控制 Android 的 VectorDrawable 动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37002677/

相关文章:

Android 改造处理 onFailure() 响应

java - 处理 fragment 内的空回收查看器

android - Viewpager 内部有多个 View ,如 "Pulse"应用程序条

android - 如何在 Android 动画结束后删除动画 View ?

android - 从 Android 应用程序连接到 mySql 数据库时应用程序崩溃

android - 图标上通知的 UI 帮助

android - 用于 viewpager 的 fakedrag 的工作示例

android - ViewPager2 - 如何使用 registerOnPageChangeCallback 检查查看寻呼机项目位置

android - 在 android 显示中的随机位置连续移动图像

android - 使用 FLAG_ACTIVITY_CLEAR_TOP 时是否无法实现过渡动画?