Android使用Canvas实现带加载动画的Button

2017-12-04  本文已影响862人  奋斗小青年Jerome

这个笔记是为了巩固之前的Canvas知识
先看一下效果图


loading.gif

其实效果看上去很简单,原理也简单,分析一下:

  1. 使用Canvas画一个普通按钮,并在点击之后从矩形逐渐先缩放成两个半圆加上中间的矩形;
  2. 从两个半圆和中间矩形组成的形状,再次渐变成最终的圆,最后在圆上绘制转动的圆圈;

现在分析一下代码怎么写:

  1. Canvas绘制带圆角的矩形,需要使用
  public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
        super.drawRoundRect(rect, rx, ry, paint);
    }

其中的参数rx指x方向上的圆角半径,ry指y方向上的圆角半径
只需要在一段时间内,让这个圆角半径等于高度的1/2,就是半圆了


image.png

ValueAnimator的addUpdateListener可以监听在一段时间内,某个元素从开始到结束的变化,并返回这个变化的因子,这个circleAngle 就是圆角的变化因子,它从0(我这里默认不绘制带圆角),变化到view高度的1/2


    /**
     * 设置矩形过度到圆角矩形的动画
     */
    private void startRoundCircleAnimation() {
        animatorRectToRound = ValueAnimator.ofInt(0, mHeight / 2);
        animatorRectToRound.setDuration(circleDuration);
        animatorRectToRound.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                circleAngle = (int) animation.getAnimatedValue();
                invalidate();
            }
        });
    }
  1. 从圆角圆角矩形到圆的变换,先看图


    image.png

    这一段就是整个View的起始宽度,最终变换成一个圆,那么中间这一段就是要压缩掉的,两个半圆合成一个圆

 /**
     * 设置圆角矩形过度到圆的动画
     */
    private void startRectRoundAnimation() {
        animatorRoundToCircle = ValueAnimator.ofInt(0, defaultDistance);
        animatorRoundToCircle.setDuration(duration);
        animatorRoundToCircle.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                //矩形完全变成圆之后,再绘制loading圆圈
                startDrawLoad = true;
                disableClick = true;
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        animatorRoundToCircle.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                circleDistance = (int) animation.getAnimatedValue();
                int alpha = 255 - (circleDistance * 255) / defaultDistance;
                textPaint.setAlpha(alpha);
                invalidate();
            }
        });
    }

这里代码直接是从圆角矩形压缩到了圆,没有做分开压缩;并且压缩过程中将字体也从不透明变到透明

  1. 绘制中间的圆圈,并旋转
  /***
     * 绘制加载圆圈
     * @param canvas
     */
    private void drawLoad(Canvas canvas) {
        canvas.translate(mWidth / 2, mHeight / 2);
        canvas.rotate(degree);
        float r = mHeight / 3;
        RectF rectf = new RectF(-r, -r, r, r);
        canvas.drawArc(rectf, 0, loadingAnge, false, loadPaint);
    }

旋转的原理:
循环的旋转画布,其实真正画的那个圆圈没有旋转,只是将后面的Canvas旋转了
drawArc就多说了,使用一个RectF来绘制扇形,扇形的最外边距就是这个矩形的外切线
注意:
注意旋转画布之前,需要将画布移动,再旋转画布才能生效
关于旋转画布
黄色部分是屏幕,蓝色部分为画布,红色为真正画的内容

canvas.translate(200, 100);
image.png

**注意:

  1. 旋转是针对于x和y坐标的(0,0)点的,x和y轴是会旋转的,
    还有一个旋转方法是canvas.rotate(90,x,y);就是绕x,y点旋转
  2. 图片永远显示在canvas中的,图片相对于canvas是没有任何变化的**
canvas.rotate(90);
image.png

参考了大神的一些讲Canvas的博客

上一篇下一篇

猜你喜欢

热点阅读