Android 自定义view实现一个方块矩阵

简介

项目中要搞一个很多小方块组成的矩阵。其实也没啥难度,不过后来写完踩了个坑,于是乎记录一下吧。先看下效果图吧,就是酱紫:

在这里插入图片描述

实现

看到这个需求脑海中已经有个大概的思路了,在确定了行数和列数后绘制矩形就是了。下面贴上自定义view的代码。

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import honeywell.com.androitstudy.R;
import honeywell.com.androitstudy.util.DataUtil;

public class MatrixView extends View {

    //每个小方块垂直间隔
    private int marginVertical = 3;
    //水平间隔
    private int marginHorizontal = 6;

    //小方块的宽
    private int rectangleWidth = 40;
    //小方块的高
    private int rectangleHeight = 30;

    //行
    private int row;
    //列
    private int column;
    //默认的宽度
    private int defaultWidth;
    //默认的高度
    private int defaultHeight;
    //画笔
    private Paint paint;
	//小方块
    RectF rectF;
    //随机数
    private int random;

    int[] randoms = new int[8];

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

    public MatrixView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MatrixView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //初始化画笔
        paint =new Paint();
        paint.setColor(getResources().getColor(R.color.colorPrimary));
        paint.setStyle(Paint.Style.FILL);
        paint.setAntiAlias(true);
        //初始化RectF
        rectF = new RectF(0,0,rectangleWidth,rectangleHeight);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    	//计算自定义view的实际宽高
        int width = getRealWidth(widthMeasureSpec);
        int height = getRealHeight(heightMeasureSpec);
        setMeasuredDimension(width,height);
    }

    private int getRealWidth(int widthMeasureSpec) {
        int result;
        int specMode = MeasureSpec.getMode(widthMeasureSpec);
        int specSize = MeasureSpec.getSize(widthMeasureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            defaultWidth = 10 * rectangleWidth + 9 * marginHorizontal;
            result = Math.min(defaultWidth, specSize);
        }
        return result;
    }

    private int getRealHeight(int heightMeasureSpec) {
        int result;
        int specMode = MeasureSpec.getMode(heightMeasureSpec);
        int specSize = MeasureSpec.getSize(heightMeasureSpec);
        //match_parent就使用得到的数值
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
        	//wrap_content就自己计算
            defaultHeight = 8 * rectangleHeight + 8 * marginVertical;
            result = Math.min(defaultHeight, specSize);
        }
        return result;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int startY = defaultHeight;
        int startX = 0;
        //行
        for(int i=0;i<8;i++){
            startY = defaultHeight;
            //列
            for(int j=0;j<10;j++){
               rectF.set(startX,startY,startX+rectangleWidth,startY+rectangleHeight);
               //这里踩坑,会导致内存抖动,解决方法就是复用receF
                //RectF rectF = new RectF(startX,startY,startX+rectangleWidth,startY+rectangleHeight);
                // 绘制带圆角的矩形 
                canvas.drawRoundRect(rectF,5,5,paint);
                startY = startY -marginVertical -rectangleHeight;
            }
            startX = startX+marginHorizontal+rectangleWidth;
        }
		//原计划矩阵需要实现波动效果,所以需要重绘,后来去掉了
        //getHandler().postDelayed(runnable,500);
    }

    private Runnable runnable=new Runnable() {
        @Override
        public void run() {
            invalidate();
        }
    };
}

总结

其实没啥好写的,注释都加了,需要注意的是在onDraw方法里面不要每次都new一个RectF,不然的话会发现在打开这个自定义view时候会发生内存抖动,一般复用都能解决此类问题。如果你也有类似需求可以直接CV了。

猜你喜欢

转载自blog.csdn.net/u012894808/article/details/106714094