View的三大流程:测量,布局,绘制
上篇Android自定义View学习(一)——准备简单介绍了部分测量的知识,后面会继续学习测量的知识。本篇记录下绘制onDraw()方法的学习,只是开始。
完成了View的测量后,根据拿到的View的大小,位置,重写onDraw(Canvas canvas)就可以进行绘制。
现实中,如果想要画一幅画,必须要有画笔和画布。Canvas就是画布,Paint就是画笔。Canvas和Patint有各种各样的属性。本篇先学习部分常用的基础的属性,一些可以高度化定制的属性后续再进行学习。
2.Canvas源码中关于Canvas的解释:
The Canvas class holds the "draw" calls. To draw something, you need 4 basic components: A Bitmap to hold the pixels, a Canvas to host the draw calls (writing into the bitmap), a drawing primitive (e.g. Rect, Path, text, Bitmap), and a paint (to describe the colors and styles for the drawing).
想要画出一个View就必须要有4个必要的元素:
翻译水平,32级 : )
Canvas有两种常见创建方法:
常用的几个绘制方法
方法 作用
drawRect() 画矩形
drawCircle() 画圆
drawArc() 画圆弧
drawRoundRect() 画圆角矩形
drawBitmap() 画一个Bitmap
drawOval 画椭圆
drawText() 画文字
Canvas的方法有很多,这里先记录几个简单的绘制方法,其他的后续学习再做补充。
2.1 drawRect() 绘制矩形drawRect()有三种重载方法:
Draw the specified Rect using the specified paint. The rectangle will be filled or framed based on the Style in the paint.
@param left The left side of the rectangle to be drawn
@param top The top side of the rectangle to be drawn
@param right The right side of the rectangle to be drawn
@param bottom The bottom side of the rectangle to be drawn
@param paint The paint used to draw the rect
MeausreView代码,主要绘制就是onDraw()方法:
public class MeasureView extends View { private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); public MeasureView(Context context) { super(context); initPaint(); } public MeasureView(Context context, AttributeSet attrs) { super(context, attrs); initPaint(); } public MeasureView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initPaint(); } private void initPaint() { paint.setColor(Color.parseColor("#FF4081")); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); float left = getLeft(); float right = getRight(); float top = getTop(); float bottom = getBottom(); canvas.drawRect(left,top,right,bottom,paint); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(measureWidth(widthMeasureSpec), measuredHeight(heightMeasureSpec)); } /** * 测量宽 * * @param widthMeasureSpec */ private int measureWidth(int widthMeasureSpec) { int result; int specMode = MeasureSpec.getMode(widthMeasureSpec); int specSize = MeasureSpec.getSize(widthMeasureSpec); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { result = 200; if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; } /** * 测量高 * * @param heightMeasureSpec */ private int measuredHeight(int heightMeasureSpec) { int result; int specMode = MeasureSpec.getMode(heightMeasureSpec); int specSize = MeasureSpec.getSize(heightMeasureSpec); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { result = 200; if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; } }在Activity的布局文件中:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.szlk.customview.custom.MeasureView android:id="@+id/mv_custom_activity" android:layout_width="200dp" android:layout_height="200dp" android:background="@color/colorPrimary" /> </LinearLayout>
绘制矩形
MeausureView的width = right - left
MeausureView的height = bottom - top
注意drawRect(left,top,right,bottom,paint)的参数顺序。
两个方法的差别在于Rect和RectF的差别。
Rect
Rect holds four integer coordinates for a rectangle. The rectangle is
represented by the coordinates of its 4 edges (left, top, right bottom).
These fields can be accessed directly. Use width() and height() to retrieve
the rectangle's width and height. Note: most methods do not check to see that the coordinates are sorted correctly (i.e. left <= right and top <= bottom).
RectF