hello,大家好,这里是第二期的代码详解。
上一期的说明个人重新看了一下发现还有逻辑没有理清,这里便补充说明一下,实现自定义view要重写三种方法,分别是onMeasure(),onLayout(),onDraw(),
1.View本身大小多少,这由onMeasure()决定;
2.View在ViewGroup中的位置如何,这由onLayout()决定;
3.绘制View,onDraw()定义了如何绘制这个View。
在这个五子棋项目中,onLayout是采取默认的,并没有重写。
话不多说,进入正题——
onMeasure()方法上一期没有说明,这一期来说明一下,代码如下:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int WidthSize = MeasureSpec.getSize(widthMeasureSpec); int WidthMode = MeasureSpec.getMode(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int width = Math.min(WidthSize, heightSize); //因为棋盘是正方形,所以取最小值, if(WidthMode == MeasureSpec.UNSPECIFIED){//MeasureSpec.UNSPECIFIED表示未知大小 width = heightSize; }else if(heightMode == MeasureSpec.UNSPECIFIED){ width = WidthSize; } setMeasuredDimension(width, width);//设置实际大小,两个width分别为长和宽,相同即是正方形 }
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)
onMeasure传入的两个参数是由上一层控件传入的大小,有多种情况,重写该方法时需要对计算控件的实际大小,然后调用setMeasuredDimension(int, int)设置实际大小。
onMeasure传入的widthMeasureSpec和heightMeasureSpec不是一般的尺寸数值,而是将模式和尺寸组合在一起的数值。
我们需要通过int mode = MeasureSpec.getMode(widthMeasureSpec)得到模式,用int size = MeasureSpec.getSize(widthMeasureSpec)得到尺寸
这个方法代码其实就是用来设置棋盘的大小的。
除此之外,还要重写一个onSizeChange()方法,代码如下:
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {//当View大小发生改变(比如分辨率变化)的时候会被系统自动回调。 super.onSizeChanged(w, h, oldw, oldh); PanelWidth =w; mLineHeight = PanelWidth * 1.0f/Max_LINE; int pieceWidth = (int)(mLineHeight*ratioPieceOfLineheight);//棋子大小占行宽的3/4 Whitepiece = Bitmap.createScaledBitmap(Whitepiece, pieceWidth, pieceWidth, false); //以src为原图,创建新的图像,指定新图像的高宽以及是否可变 Blackpiece = Bitmap.createScaledBitmap(Blackpiece, pieceWidth, pieceWidth, false); }
解释标记出来了,这里也就不啰嗦什么了。
接下来解释的是onDraw()方法里面的drawBoard()方法。代码如下:
private void drawBoard(Canvas canvas) { int w = PanelWidth; float LineHeight = mLineHeight; for(int i=0;i<Max_LINE;i++){ //画十条线 int startX = (int)(LineHeight/2);//设置起点横坐标为半个棋盘空格的宽度 int endX = (int)(w-LineHeight/2);//设置终点X横坐标为宽度减去半个lineHeight(棋盘空格宽度) int y =(int)((0.5+i)*LineHeight); canvas.drawLine(startX, y, endX, y, paint);//画横线 canvas.drawLine(y, startX, y, endX, paint);//画纵线,坐标反过来 } }
正如其名,drawBoard()就是用来画棋盘的,通过for循环画出横线,这里的注释需要仔细地思索一下,想清楚画笔起始坐标是如何计算得出的
这一期就到这里了,下面附上参考资料: