View绘制流程简介

来源:互联网 发布:如何将链接在淘宝打开 编辑:程序博客网 时间:2024/05/16 10:35

简单梳理一下View的绘制流程。View的绘制分为三个部分(mechanism),分别为:measure,layout,draw。


第一部分:Measure

这一过程负责确定各个View的大小,得到的结果存放在每个ViewmMeasuredWidthmMeasuredHeight中。

该部分主要有三个函数:

measure(int widthMeasureSpec, int heightMeasureSpec);onMeasure(int widthMeasureSpec, int heightMeasureSpec);setMeasuredDimension(int measuredWidth, int measuredHeight);

measure(int, int)

发起measure过程,需要用到两类信息:

  1. MeasureSpecs,父View对子View的要求,有三种模式:UNSPECIFIEDEXACTLYAT_MOST
  2. ViewGroup.LayoutParams,子View自身的布局参数,可以是具体值、MATCH_PARENTWRAP_CONTENT

该方法为final方法,不可被Override,该方法会调用onMeasure(),一般情况下子类应该Override onMeasure()方法。

onMeasure(int, int)

进行具体的测量工作,该函数的参数是mMeasuredWidthmMeasuredHeight,即父View对我们的测量要求,要做的工作就是根据父View的大小确定自己的大小。如果是ViewGroup,还要调用子Viewmeasure(int, int)才能确定自己的大小。同时这一步的最后需要调用setMeasuredDimension(int, int)将测量结果存储起来,否则在使用过程中会抛出异常。

setMeasuredDimension(int, int)

将测量结果存储在mMeasuredWidthmMeasuredHeight中,在之后的步骤中,可以通过getMeasuredWidth()getMeasuredHeight()获取这两个参数。


第二部分:Layout

这一部分通过Measure中得到的各个View的大小,确定各个View的摆放位置。

该部分主要有两个函数:

layout(int l, int t, int r, int b);onLayout(boolean changed, int l, int t, int r, int b);

相对于measure,这部分比较简单,最后会通过setFrame(int, int, int, int)确定各个View相对于父View的坐标。

第三部分:Draw

该部分绘制View的内容。

主要有两个函数:

draw(Canvas canvas);onDraw(Canva canvas);

draw(Canvas)

代码略长,但主要工作是调用onDraw()绘制自己,然后调用dispatchDraw()绘制子View

根据文档说明,该方法负责渲染将View以及所有子View渲染到Canvas,必须在layout完成后调用,一般不应该Override该方法,如果要继承,可以Override onDraw()方法。

也就是说自定义View的时候基本可以不考虑这个方法。

onDraw(Canvas)

ViewonDraw()方法为空实现,subclass一般要Override该方法,绘制自己。

比如,想绘制一个矩形:

// 画一个起点坐标(0,0),终点坐标(10,20)的矩形Paint paint = new Paint();paint.setAntiAlias(true);paint.setColor(Color.BLUE);paint.setStyle(Paint.Style.FILL);canvas.drawRect(0, 0, 10, 20, paint);

dispatchDraw(Canvas)

调用子Viewdraw()方法,绘制子View

0 0