美文网首页
Android自定义View(3)画两个好玩的数据加载进度缓冲控

Android自定义View(3)画两个好玩的数据加载进度缓冲控

作者: 碧云天EthanLee | 来源:发表于2021-02-21 18:40 被阅读0次
    1、仿58同城数据加载缓冲控件动画效果

    先看下效果图:

    58city.gif
    #######1.1 实现步骤拆解
    (1)自定义一个ShapeView继承自View,按顺序分别重绘三角形、圆形和正方形,如此不断重复。
    (2)自定义一个ViewGroup,创建一个ShapeView加进布局当中,并往布局中再添加一个TextView以显示文字。onLayout分别摆放好ShapeView和TextView。
    (3)使用属性动画实现ShapeView的上下移动和旋转

    #######1.2 实现分析
    2.1 自定义一个ShapeView
    自定义一个ShapeView实现三种形状切换效果的原理也很简单。圆形通过画布的canvas.drawCircle()方法来绘制,正方形通过画布的canvas.drawRect()方法来绘制。等边三角形的绘制稍复杂,可通过绘制路径来实现: canvas.drawPath(),等边三角形路径的三个顶点坐标通过计算得出,以下是分析图 :


    triangle.png

    如上图,控件ShapeView的宽高可通过getMeasureHeight()或getMeasureWidth()获得,这里测量时已确保ShapeView的宽高相等。因此,三角形边长S即为控件宽或高。
    然后,如上图,三角形的三个顶点A 、B 、C即可通过勾股定理算出。
    三角形路径设置代码如下:

    Path trianglePath = new Path();
    trianglePath.moveTo(getWidth() / 2f, 0);
    trianglePath.lineTo(0, (float) (Math.sqrt(3) * getHeight() / 2)); // 等边三角形
    trianglePath.lineTo(getWidth(), (float) (Math.sqrt(3) * getHeight() / 2));
    trianglePath.close();
    

    确定好三个形状的绘制方法后,就可以循环地延时一秒钟,不断地改变当前所要绘制的图形形状,调用 invalidate()方法实现图形的重绘。三种图形绘制方法如下 :

     @Override
        protected void onDraw(Canvas canvas) {
            switch (mShape) { // 当前所要绘制的形状
                case circle:  // 圆
                    canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, getHeight() / 2f, circlePaint);
                    break;
                case rect:  // 正方形
                    canvas.drawRect(0, 0, getWidth(), getHeight(), rectPaint);
                    break;
                case triangle: // 三角形
                    canvas.drawPath(trianglePath, trianglePaint);
                    break;
            }
        }
    

    ShapeView的代码见 :https://github.com/EthanLee-88/LoadingView/blob/master/app/src/main/java/com/ethan/loadingview/view/ShapeView.java

    2.2 自定义一个布局ShapeChangeLoadingViewGroup。

    第二步骤就是自定义一个布局ShapeChangeLoadingViewGroup,继承自ViewGroup。再创建ShapeView和一个TextView,TextView用于显示文字“拼命加载中...”。这个步骤的主要内容在于布局,将TextView放在ViewGroup的最底部,ShapeView放在上面。ShapeChangeLoadingViewGroup的布局部分代码如下 :

    @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            int shapeLeft = getWidth() / 2 - mShapeView.getMeasuredWidth() / 2;
            int shapeTop = (int) (mShapeView.getMeasuredHeight() * 3.5);
            int shapeRight = shapeLeft + mShapeView.getMeasuredWidth();
            int shapeBottom = shapeTop + mShapeView.getMeasuredHeight();
            mShapeView.layout(shapeLeft, shapeTop, shapeRight, shapeBottom);
            int textLeft = 0;
            int textTop = getHeight() - mLoadTextView.getMeasuredHeight();
            int textRight = getWidth();
            int textBottom = getHeight();
            mLoadTextView.layout(textLeft, textTop, textRight, textBottom);
            setAnimator();
        }
    

    2.3 使用属性动画让ShapeView动起来
    第三部就是实现ShapeView上下移动以及旋转的效果,这里分别使用了属性动画的translationY 和 rotation 两个属性实现。代码如下 :

            translationObjectAnimator = ObjectAnimator.ofFloat(mShapeView,
                    "translationY", -distance, 0, -distance);  //实现上下平移
            translationObjectAnimator.setDuration(1500);
            translationObjectAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
            translationObjectAnimator.setRepeatCount(-1);  // -1 无限循环
    
            rotationObjectAnimator = ObjectAnimator.ofFloat(mShapeView,
                    "rotation", 0f, 360f);  // 实现360度旋转
            rotationObjectAnimator.setDuration(1500);
            rotationObjectAnimator.setRepeatCount(-1);  // -1 无限循环
    
            rotationObjectAnimator.start();
            translationObjectAnimator.start();
    
    

    最后效果实现了,但有一点要优化。对外提供一个接口,将属性动画资源释放 :

    public void release(){  //优化,释放属性动画资源
            if (translationObjectAnimator != null){
                translationObjectAnimator.end();
                translationObjectAnimator.removeAllListeners();
                translationObjectAnimator.cancel();
                translationObjectAnimator = null;
            }
            if (rotationObjectAnimator != null){
                rotationObjectAnimator.end();
                rotationObjectAnimator.removeAllListeners();
                rotationObjectAnimator.cancel();
                rotationObjectAnimator = null;
            }
            if (mShapeView != null) mShapeView.setRepeat(false);
        }
    

    完整代码 :https://github.com/EthanLee-88/LoadingView

    2、另一个加载控件

    效果看图 :

    loadingView.gif
    实现步骤 :
    (1) 自定义一个CircleView继承自View,画一个圆,对外提供可改变颜色的接口。
    (2) 自定义一个LoadingView继承自ViewGroup,创建三个CircleView,分别摆放在LoadingView的左、中、右的位置。
    (3) 利用属性动画实现左右两个CircleView往中间方向来回移动,中间的CircleView保持不动。
    (4) 监听属性动画的回调,实现每移动一次,三个CircleView颜色互换一次,达到变色的效果。
    这部分实现比较简单,实现原理和上面第一个控件相似,这里不再详细讲述。看源码:https://github.com/EthanLee-88/LoadingView

    相关文章

      网友评论

          本文标题:Android自定义View(3)画两个好玩的数据加载进度缓冲控

          本文链接:https://www.haomeiwen.com/subject/jceqfltx.html