Android中利用矢量动画制作支付宝支付成功样式

之前我们学习了矢量动画,今天就利用适量动画制作一个支付宝支付成功后打钩的动画。其实这个动画简单描述如下:首先它会画一个圈,接着在圈内打个对勾。这个效果在很多地方都可以使用,比如提交成功,压缩成功等一系列耗时操作之后显示。好了,废话不多说,还是老规矩,一步一步跟着来。

1.分析

这个动画包含了两部分,一部分是画圈动画,另一部分是打钩动画。画圈动画结束后才开始打钩动画,所以他们是有顺序的。

2.画圈动画

animated_pay_circle.xml

<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/vector_pay_circle_white">

    <target
        android:name="circle"
        android:animation="@animator/anim_pay" />

</animated-vector>

anim_pay.xml

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:interpolator="@android:interpolator/linear"
    android:propertyName="trimPathEnd"
    android:valueFrom="0"
    android:valueTo="1"
    android:valueType="floatType" /><!--trimPathStart就是利用0到1的百分比来按照轨迹绘制SVG图像。类似的,还有trimPathEnd这个属性。-->

vector_pay_circle_white.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="100dp"
    android:viewportHeight="100"
    android:viewportWidth="100"
    android:width="100dp">

    <path
        android:name="circle"
        android:pathData="
            M 10,50
            A 40 40 0 1 0 10 49"
        android:strokeAlpha="1"
        android:strokeColor="@android:color/holo_blue_dark"
        android:strokeLineCap="round"
        android:strokeWidth="5" />

</vector>

布局文件中activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:id="@+id/iv"
        android:layout_centerInParent="true"/>

</RelativeLayout>

Activity中MainActivity.java

public class MainActivity extends AppCompatActivity {

    private ImageView iv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iv = findViewById(R.id.iv);
        startVectorAnim(R.drawable.animated_pay_circle);
        //准备后续动画的开始

    }

    // 开始播放矢量动画
    private void startVectorAnim(int drawableId) {
        // 从指定资源编号的矢量文件中获取图形对象
        Drawable mDrawable = getResources().getDrawable(drawableId);
        int dip_50 = dip2px(this, 50);
        iv.setImageDrawable(mDrawable);
        // 将该图形强制转换为动画图形,并开始播放
        ((Animatable) mDrawable).start();
    }

    private int dip2px(Context context, float dpValue) {
        // 获取当前手机的像素密度
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f); // 四舍五入取整
    }
}

到这里我们就可以先运行一下了,可以看到有一个画圈的动画已经完成。

2.判断画圈结束

接着我们就要判断画圈动画结束,为打钩动画做准备。细心的同学已经看到Activity中我已经留了注释。所以我们修改Activity如下:

public class MainActivity extends AppCompatActivity {

    private ImageView iv;
    private Drawable mDrawable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iv = findViewById(R.id.iv);
        startVectorAnim(R.drawable.animated_pay_circle);
        //准备后续动画的开始
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // 为画圈动画注册一个矢量动画图形的监听器
            ((AnimatedVectorDrawable) mDrawable)
                    .registerAnimationCallback(new VectorAnimListener());
        } else {
            // 延迟1秒后启动打勾动画的播放任务
            new Handler().postDelayed(mHookRunnable, 1000);
        }
    }

    // 开始播放矢量动画
    private void startVectorAnim(int drawableId) {
        // 从指定资源编号的矢量文件中获取图形对象
        mDrawable = getResources().getDrawable(drawableId);
        int dip_50 = dip2px(this, 50);
        iv.setImageDrawable(mDrawable);
        // 将该图形强制转换为动画图形,并开始播放
        ((Animatable) mDrawable).start();
    }

    private int dip2px(Context context, float dpValue) {
        // 获取当前手机的像素密度
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f); // 四舍五入取整
    }

    // 定义一个动画图形的监听器
    @TargetApi(Build.VERSION_CODES.M)
    private class VectorAnimListener extends Animatable2.AnimationCallback {
        // 在动画图形开始播放时触发
        public void onAnimationStart(Drawable drawable) {}

        // 在动画图形结束播放时触发
        public void onAnimationEnd(Drawable drawable) {
            // 开始播放打勾的矢量动画
//            startVectorAnim(R.drawable.animated_pay_success);
        }
    }

    // 定义一个打勾动画的播放任务
    private Runnable mHookRunnable = new Runnable() {
        @Override
        public void run() {
            // 开始播放打勾的矢量动画
//            startVectorAnim(R.drawable.animated_pay_success);
        }
    };
}

3.完成打钩动画

我们既然确定了画圈动画结束的时刻,就可以开始打钩了。

animated_pay_success.xml

<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/vector_pay_success_white">

    <target
        android:name="hook"
        android:animation="@animator/anim_pay" />

</animated-vector>

vector_pay_success_white.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="100dp"
    android:viewportHeight="100"
    android:viewportWidth="100"
    android:width="100dp">

    <path
        android:name="circle"
        android:pathData="
            M 10,50
            A 40 40 0 1 0 10 49"
        android:strokeAlpha="1"
        android:strokeColor="@android:color/holo_blue_dark"
        android:strokeLineCap="round"
        android:strokeWidth="5" />
    <path
        android:name="hook"
        android:pathData="
            M 30,50
            L 45 65
            L 75 35"
        android:strokeAlpha="1"
        android:strokeColor="@android:color/holo_blue_dark"
        android:strokeLineCap="butt"
        android:strokeWidth="5" />

</vector>

修改我们的Activity代码如下

public class MainActivity extends AppCompatActivity {

    private ImageView iv;
    private Drawable mDrawable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iv = findViewById(R.id.iv);
        startVectorAnim(R.drawable.animated_pay_circle);
        //准备后续动画的开始
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // 为画圈动画注册一个矢量动画图形的监听器
            ((AnimatedVectorDrawable) mDrawable)
                    .registerAnimationCallback(new VectorAnimListener());
        } else {
            // 延迟1秒后启动打勾动画的播放任务
            new Handler().postDelayed(mHookRunnable, 1000);
        }
    }

    // 开始播放矢量动画
    private void startVectorAnim(int drawableId) {
        // 从指定资源编号的矢量文件中获取图形对象
        mDrawable = getResources().getDrawable(drawableId);
        int dip_50 = dip2px(this, 50);
        iv.setImageDrawable(mDrawable);
        // 将该图形强制转换为动画图形,并开始播放
        ((Animatable) mDrawable).start();
    }

    private int dip2px(Context context, float dpValue) {
        // 获取当前手机的像素密度
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f); // 四舍五入取整
    }

    // 定义一个动画图形的监听器
    @TargetApi(Build.VERSION_CODES.M)
    private class VectorAnimListener extends Animatable2.AnimationCallback {
        // 在动画图形开始播放时触发
        public void onAnimationStart(Drawable drawable) {}

        // 在动画图形结束播放时触发
        public void onAnimationEnd(Drawable drawable) {
            // 开始播放打勾的矢量动画
            startVectorAnim(R.drawable.animated_pay_success);
        }
    }

    // 定义一个打勾动画的播放任务
    private Runnable mHookRunnable = new Runnable() {
        @Override
        public void run() {
            // 开始播放打勾的矢量动画
            startVectorAnim(R.drawable.animated_pay_success);
        }
    };
}

这样我们就完成了一个打钩的适量动画。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值