Android 自定义LoadingView

 

Android 自定义LoadingView

 

                                作者:郑州阿斯特网络科技有限公司

                                             https://www.astgo.net

 

对于安卓程序员来说,无论你是叱咤职场的大牛还是刚入行的菜鸟,自定义view简直不要太重要。不知道有没有遇到过UI一不留神设计的太炫了,但是android原生却没有这样的效果,她还死扣非要这种效果,说到这怎么感觉背后一阵风,不皮了。

下面,我们就用最简单方式来尝试下如何自定义一个自己的view~

 

前言:

自定义View的流程

(1).自定义View的属性(非必需)
(2).View的构造方法中获得我们自定义的属性(非必需)
(3).重写onMesure
(4).重写onDraw

 

我们就开始吧!

—、onMeasure()

UNSPECIFIED

父容器没有对当前View有任何限制,要多大就多大,这种情况一般用于系统内部,表示一种测量状态

EXACTLY

父容器已经检查出View所需要的精确大小,这时候View的最终大小就是getSize中返回的值

AT_MOST

父容器制定了一个View可用的大小,但View大小不能大于这个

 

测量模式跟布局时用到的wrap_contentmatch_parent以及固定的尺寸的对应关系如下:
EXACTLY对应为:match_parent和固定尺寸
AT_MOST对应为:wrap_content

UNSPECIFIED:表示子布局想要多大就多大,很少使用

 

 

理论有了,得有实操吧,代码注释很清晰就不多说了

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    //根据个人习惯设置 这里设置 如果是wrap_content  则设置为宽高200
    if (widthMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.AT_MOST) {
        width = 200;/设置默认

    } else {
        width = MeasureSpec.getSize(widthMeasureSpec);
        height = MeasureSpec.getSize(heightMeasureSpec);
        width = Math.min(width, height);
    }

    widthRect = width / 12;   //菊花矩形的宽
    heightRect = 3 * widthRect;  //菊花矩形的高
    setMeasuredDimension(width, width);
}

 

 

 

 

二、onDraw

 该方法里我们利用android 提供的api绘制出我们想要的效果

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //绘制部分是关键了,菊花花瓣矩形有12个,我们不可能去一个一个的算出所有的矩形坐标
    //所以我算出一个矩形位置
    // 然后旋转下面的画布canvas来实现绘制,每次旋转 360/12 = 30 


    //垂直方向上面矩形
    //矩形左上角
    // left:矩形的左边位置。
    //  top:矩形的上边位置。
    //矩形右下角
    //right:矩形的右边位置。
    //bottom:矩形的下边位置。
    if (rect == null) {
        rect = new Rect((width - widthRect) / 2, 0, (width + widthRect) / 2, heightRect);
    }
    //canvas.drawRect(rect, rectPaint);  //绘制
    //       0  1  2  3  4  5  6  7  8  9  10  11   i的值
    // ————————————————————————————————————————————————————————
    //  0   ‖ 0 | 1 | 2 | 3 | 4 | 5 | 5 | 5 | 5 | 5 | 5 | 5 ‖
    //  1   ‖ 5 | 0 | 1 | 2 | 3 | 4 | 5 | 5 | 5 | 5 | 5 | 5 ‖
    //  2   ‖ 5 | 5 | 0 | 1 | 2 | 3 | 4 | 5 | 5 | 5 | 5 | 5 ‖
    //  3   ‖ 5 | 5 | 5 | 0 | 1 | 2 | 3 | 4 | 5 | 5 | 5 | 5 ‖
    //  4   ‖ 5 | 5 | 5 | 5 | 0 | 1 | 2 | 3 | 4 | 5 | 5 | 5 ‖
    //  5   ‖ 5 | 5 | 5 | 5 | 5 | 0 | 1 | 2 | 3 | 4 | 5 | 5 ‖
    //  6   ‖ 5 | 5 | 5 | 5 | 5 | 5 | 0 | 1 | 2 | 3 | 4 | 5 ‖
    //  7   ‖ 5 | 5 | 5 | 5 | 5 | 5 | 5 | 0 | 1 | 2 | 3 | 4 ‖
    //  8   ‖ 4 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 0 | 1 | 2 | 3 ‖
    //  9   ‖ 3 | 4 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 0 | 1 | 2 ‖
    //  10   ‖ 2 | 3 | 4 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 0 | 1 ‖
    //  11   ‖ 1 | 2 | 3 | 4 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 0 ‖
    //  pos的值
    for (int i = 0; i < 12; i++) {
        if (i - pos >= 5) {
            rectPaint.setColor(Color.parseColor(color[5]));
        } else if (i - pos >= 0 && i - pos < 5) {
            rectPaint.setColor(Color.parseColor(color[i - pos]));
        } else if (i - pos >= -7 && i - pos < 0) {
            rectPaint.setColor(Color.parseColor(color[5]));
        } else if (i - pos >= -11 && i - pos < -7) {
            rectPaint.setColor(Color.parseColor(color[12 + i - pos]));
        }

        canvas.drawRect(rect, rectPaint);  //绘制
        canvas.rotate(30, width / 2, width / 2);    //旋转
    }

    pos++;
    if (pos > 11) {
        pos = 0;
    }
    if (isAttached) {
        postInvalidateDelayed(100);  //一个周期用时1200
    }

}

 

 

最后附上完整demo

package com.example.customview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;

/**
 * 2020102417:08:20
 * 自定义简单的菊花加载中View
 */
public class LoadingView extends View {

    private static final String TAG = LoadingView.class.getSimpleName();
    /**
     * view宽度
     */
    private int width;
    /**
     * view高度
     */
    private int height;
    /**
     * 菊花的矩形的宽
     */
    private int widthRect;
    /**
     * 菊花的矩形的长
     */
    private int heightRect;
    /**
     * 菊花绘制画笔
     */
    private Paint rectPaint;
    /**
     * 循环绘制位置
     */
    private int pos = 0;
    /**
     * 菊花矩形
     */
    private Rect rect;
    /**
     * 循环颜色
     */
    private String[] color = {"#bbbbbb", "#aaaaaa", "#999999", "#888888", "#777777", "#666666",};

    /**
     * 是否处理活动
     *
     * @param context
     */
    private boolean isAttached = false;

    public LoadingView(Context context) {
        this(context, null);
    }

    public LoadingView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    private void init() {
        rectPaint = new Paint();
        rectPaint.setAntiAlias(true);

    }

    //onResume后调用
    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        isAttached = true;
    }

    //onDestroy后调用
    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        isAttached = false;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        //根据个人习惯设置 这里设置 如果是wrap_content  则设置为宽高200
        if (widthMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.AT_MOST) {
            width = 200;
        } else {
            width = MeasureSpec.getSize(widthMeasureSpec);
            height = MeasureSpec.getSize(heightMeasureSpec);
            width = Math.min(width, height);
        }

        widthRect = width / 12;   //菊花矩形的宽
        heightRect = 3 * widthRect;  //菊花矩形的高
        setMeasuredDimension(width, width);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制部分是关键了,菊花花瓣矩形有12个,我们不可能去一个一个的算出所有的矩形坐标
        //所以我算出一个矩形位置
        // 然后旋转下面的画布canvas来实现绘制,每次旋转 360/12 = 30 


        //垂直方向上面矩形
        //矩形左上角
        // left:矩形的左边位置。
        //  top:矩形的上边位置。
        //矩形右下角
        //right:矩形的右边位置。
        //bottom:矩形的下边位置。
        if (rect == null) {
            rect = new Rect((width - widthRect) / 2, 0, (width + widthRect) / 2, heightRect);
        }
        //canvas.drawRect(rect, rectPaint);  //绘制
        //       0  1  2  3  4  5  6  7  8  9  10  11   i的值
        // ————————————————————————————————————————————————————————
        //  0   ‖ 0 | 1 | 2 | 3 | 4 | 5 | 5 | 5 | 5 | 5 | 5 | 5 ‖
        //  1   ‖ 5 | 0 | 1 | 2 | 3 | 4 | 5 | 5 | 5 | 5 | 5 | 5 ‖
        //  2   ‖ 5 | 5 | 0 | 1 | 2 | 3 | 4 | 5 | 5 | 5 | 5 | 5 ‖
        //  3   ‖ 5 | 5 | 5 | 0 | 1 | 2 | 3 | 4 | 5 | 5 | 5 | 5 ‖
        //  4   ‖ 5 | 5 | 5 | 5 | 0 | 1 | 2 | 3 | 4 | 5 | 5 | 5 ‖
        //  5   ‖ 5 | 5 | 5 | 5 | 5 | 0 | 1 | 2 | 3 | 4 | 5 | 5 ‖
        //  6   ‖ 5 | 5 | 5 | 5 | 5 | 5 | 0 | 1 | 2 | 3 | 4 | 5 ‖
        //  7   ‖ 5 | 5 | 5 | 5 | 5 | 5 | 5 | 0 | 1 | 2 | 3 | 4 ‖
        //  8   ‖ 4 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 0 | 1 | 2 | 3 ‖
        //  9   ‖ 3 | 4 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 0 | 1 | 2 ‖
        //  10   ‖ 2 | 3 | 4 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 0 | 1 ‖
        //  11   ‖ 1 | 2 | 3 | 4 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 0 ‖
        //  pos的值
        for (int i = 0; i < 12; i++) {
            if (i - pos >= 5) {
                rectPaint.setColor(Color.parseColor(color[5]));
            } else if (i - pos >= 0 && i - pos < 5) {
                rectPaint.setColor(Color.parseColor(color[i - pos]));
            } else if (i - pos >= -7 && i - pos < 0) {
                rectPaint.setColor(Color.parseColor(color[5]));
            } else if (i - pos >= -11 && i - pos < -7) {
                rectPaint.setColor(Color.parseColor(color[12 + i - pos]));
            }

            canvas.drawRect(rect, rectPaint);  //绘制
            canvas.rotate(30, width / 2, width / 2);    //旋转
        }

        pos++;
        if (pos > 11) {
            pos = 0;
        }
        if (isAttached) {
            postInvalidateDelayed(100);  //一个周期用时1200
        }

    }


}

 

郑州阿斯特网络科技有限公司

                                             https://www.astgo.net

posted on 2020-10-24 19:02  QQ10053660  阅读(518)  评论(0编辑  收藏  举报