Android 自定义View学习(二)

      2020-09-14 14:29      HTML5

View的三大流程:测量,布局,绘制
上篇Android自定义View学习(一)——准备简单介绍了部分测量的知识,后面会继续学习测量的知识。本篇记录下绘制onDraw()方法的学习,只是开始。

1.View的绘制

完成了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有两种常见创建方法:

Canvas canvas = new Canvas() 空参构造方法Canvas canvas = new Canvas(bitmap) 创建一个装载画布。构造方法中传入的bitmap存储所有绘制在canvas的信息。

常用的几个绘制方法

方法作用

drawRect()画矩形

drawCircle()画圆

drawArc()画圆弧

drawRoundRect()画圆角矩形

drawBitmap()画一个Bitmap

drawOval画椭圆

drawText()画文字

Canvas的方法有很多,这里先记录几个简单的绘制方法,其他的后续学习再做补充。

2.1 drawRect() 绘制矩形

drawRect()有三种重载方法:

drawRect(float left, float top, float right, float bottom, @NonNull Paint paint)

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"));}@Overrideprotected 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);}@Overrideprotected 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.MeasureViewandroid: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)的参数顺序。

drawRect(@NonNull Rect r, @NonNull Paint paint)drawRect(@NonNull RectF r, @NonNull Paint 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