简介
项目中要搞一个很多小方块组成的矩阵。其实也没啥难度,不过后来写完踩了个坑,于是乎记录一下吧。先看下效果图吧,就是酱紫:
实现
看到这个需求脑海中已经有个大概的思路了,在确定了行数和列数后绘制矩形就是了。下面贴上自定义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了。