从箭头到勾号的形变动画逆转

17

我正在尝试实现图像变形效果,当用户点击myButton时,ImageView内的图像应从箭头变形为勾号。当再次单击时,过程应反转:勾号应变形为箭头。

这是我所做的:

animated_vector.xml:

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/vector_upvote">

    <target
        android:name="rotationGroup"
        android:animation="@anim/rotate_a_to_b" />

    <target
        android:name="upvote"
        android:animation="@animator/animator_upvote_to_checkmark" />
</animated-vector>

animator_upvote_to_checkmark.xml:

<objectAnimator
    android:duration="250"
    android:propertyName="pathData"
    android:valueFrom="@string/svg_upvote"
    android:valueTo="@string/svg_checkmark"
    android:valueType="pathType"
    android:repeatMode="reverse" />

这是我播放动画的方式:

            Drawable drawable = upVote.getDrawable();
            if (drawable instanceof Animatable) {

                ((Animatable) drawable).start();
            }

这会将箭头变成勾选符号,我该如何反转这个过程?

2个回答

26

如果您的视图是checkable,并且您的minsdk > 21,则可以尝试使用StateListAnimatorAnimatedVectorDrawable,但由于appcompat现在支持vectorDrawableAnimatedVectorDrawable,并且对于使用所有DrawableContainers有限制,因此我不采用上述方法。

所以让我告诉你可能有效的方法:

引用其他仅包含矢量资源的可绘制资源的DrawableContainers。例如,引用其他文件包含矢量图形的StateListDrawable。

来自Chris Banes的建议。

为了实现这一点,我将创建自定义ImageView,每次单击它时,您必须调用morph函数来运行适当的vectorAnimatorDrawable

所以代码和演示:

enter image description here

public class ArrowToCheckMarkMorphingImageView extends ImageView {

    private AnimatedVectorDrawable mArrowToCheckMark;
    private AnimatedVectorDrawable mCheckMarkToArrow;
    private boolean mIsShowingCheckMark;
    public ArrowToCheckMarkMorphingImageView(Context context) {
        super(context);
        init();
    }

    public ArrowToCheckMarkMorphingImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ArrowToCheckMarkMorphingImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public ArrowToCheckMarkMorphingImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    public void init(){
        mIsShowingCheckMark = false;
        mArrowToCheckMark =
                (AnimatedVectorDrawable)getContext().getDrawable(R.drawable.arrow_to_checkmark);
        mCheckMarkToArrow =
                (AnimatedVectorDrawable)getContext().getDrawable(R.drawable.checkmark_to_arrow);
        setImageDrawable(mArrowToCheckMark);
    }

    public void morph(){
        final AnimatedVectorDrawable drawable
                = mIsShowingCheckMark ? mCheckMarkToArrow : mArrowToCheckMark;
        setImageDrawable(drawable);
        drawable.start();
        mIsShowingCheckMark = !mIsShowingCheckMark;
    }

}

MainActivity

public class MainActivity extends AppCompatActivity {

    ArrowToCheckMarkMorphingImageView mArrowToCheckMarkImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        mArrowToCheckMarkImageView = (ArrowToCheckMarkMorphingImageView)findViewById(R.id.imageView);
        mArrowToCheckMarkImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mArrowToCheckMarkImageView.morph();
            }
        });
    }
}

在布局文件中,您必须像这样使用它:

  <yourpackage.ArrowToCheckMarkMorphingImageView
        android:id="@+id/imageView"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_centerInParent="true"
        />

对于那些想尝试的人来说,以下是一些资源:

res/animator/arrow_to_checkmark

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:duration="500"
        android:propertyName="pathData"
        android:valueFrom="M7.41,15.41 L12,10.83 l4.59,4.58 L18,14 18,14 l-6,-6 -6,6z"
        android:valueTo  ="M9,16.17 L4.83,12 l-1.42,1.41 L9,19 21,7 l-1.41,-1.41 0,0z"
        android:valueType="pathType" />
    <objectAnimator
        android:duration="500"
        android:propertyName="fillColor"
        android:valueFrom="#FF0000FF"
        android:valueTo="#FF00FF00" />
</set>

res/animator/checkmark_to_arrow

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:duration="500"
        android:propertyName="pathData"
        android:valueFrom="M9,16.17 L4.83,12 l-1.42,1.41 L9,19 21,7 l-1.41,-1.41 0,0z"
        android:valueTo  ="M7.41,15.41 L12,10.83 l4.59,4.58 L18,14 18,14 l-6,-6 -6,6z"
        android:valueType="pathType" />
    <objectAnimator
        android:duration="500"
        android:propertyName="fillColor"
        android:valueFrom="#FF00FF00"
        android:valueTo="#FF0000FF" />
</set>

res/drawable/arrow_to_checkmark

的中文意思是:

资源/可绘制/箭头到复选标记


<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_arrow_up_24dp">
    <target
        android:animation="@animator/arrow_to_checkmark"
        android:name="arrow"/>
</animated-vector>

res/drawable/checkmark_to_arrow

的中文翻译是:

res/drawable/checkmark_to_arrow


<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_checkmark_24dp">
    <target
        android:animation="@animator/checkmark_to_arrow"
        android:name="checkmark"/>
</animated-vector>

res/drawable/ic_arrow_up_24dp

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:name="arrow"
        android:fillColor="#FF0000FF"
        android:pathData="M7.41,15.41 L12,10.83 l4.59,4.58 L18,14 18,14 l-6,-6 -6,6z"/>
</vector>

res/drawable/ic_checkmark_24dp

的内容与编程有关。
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:name="checkmark"
        android:fillColor="#FF00FF00"
        android:pathData="M9,16.17 L4.83,12 l-1.42,1.41 L9,19 21,7 l-1.41,-1.41 0,0z"/>
</vector>

2
感谢您的解释 - 正在进行这个确切的事情。似乎需要很多努力,即代码/文件,才能实现相当基本的动画! - Mark
@MarkKeen 只是想这样做,而答案将代码拆分为多个文件以进行结构化,我认为有点过度了,如果您不拆分动画xml,则代码会变得更小。拆分的烦人之处在于您仍然必须在可绘制对象和动画中复制路径数据。 - Adam

9

我会选择使用圆形进度按钮,你可以根据需要自定义它或扩展库(因为它是开源的)。我已经使用它有一段时间了,它非常容易集成到你的项目中。

此外,你可以从中学习并创建自己的库 :-)

这里是Git仓库CircularProgressButton

输入图片描述

另外,你也可以尝试其他优秀的开源库,例如 Android Morphing Button

输入图片描述 输入图片描述


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接