View的绘制流程

阅读 71

2021-10-09

一个应用启动时,会启动一个主Activity,Android 系统会根据activity的布局来对它进行绘制。绘制会从根视图ViewRoot的performTraversals()

方法开始,从上到下遍历整个视图树,每个view控制负责绘制自己,而ViewGroup还需要负责通知自己的子view进行绘制操作。视图绘制的过程

可以分为三个步骤,分别是测量(measure)、布局(layout)和绘制(Draw)。

performTraversals()方法中主要分为三个步骤:performMeasure、performLayout、performDraw

Measure:performMeasure()方法中执行view的measure方法,具体的测量操作是分发给ViewGroup的,由ViewGroup在它的measureChild方法中传递

给子view,遍历所有的子view,逐个调用子view的measure方法。最终测量是通过回调onMeasure方法实现的。如果要自定义测量过程。则子类

可以重写onMeasure方法,如果没有重写onMeasure方法,则默认会直接调用getDefaultSize来获得View的宽高。

Layout:layout过程用来确定View在父容器中的布局位置,它是由父容器获取子view的位置参数后,调用view的layout方法并将位置参数传入实现的,

performLayout  --->layout----->onLayout(changed,l,t,r,b)

子类如果是ViewGroup类型,则重写这个方法,实现ViewGroup中所有view控件的布局流程。

Draw:draw操作用来将控件绘制出来,绘制的流程从performDraw方法开始,

performDraw----> draw----->

绘制每个具体的view,绘制基本上可以分为六个步骤:

(1)drawBackground(canvas)绘制view的背景

(2)canvas.getSaveCount()  canvas.saveLayer( )  需要的话,保存canvas的图层,为fading做准备

(3)onDraw(canvas) 绘制view的内容

(4)dispatchDraw(canvas)绘制view的子view

(5)canvas.drawRect()  canvas.restoreToCount()如果需要的话,绘制view的fading边缘并恢复图层

(6)绘制view的装饰(例如滚动条)

view的绘制几个方法需要追溯到android本身的页面结构,首先整体上市一个phoneWindow对象,然后是一个DecorView,DecorView本身是一个Framelayout,内部维护一个ViewStub的toolBar,然后下面是一个FrameLayout,,也就是我们通常setContentView中的content内容,然后是绘制,首先会触发DecorView的onMeasure()方法,它的测量规则包含了手机屏幕的宽高,并且测量模式是MeasureSpec.EXACTLY,

几种父布局测量模式与子view测量模式组合:

1、当viewGroup是MeasureSpec.EXACTLY:
(1)子view是具体值,例如200dp,那么子view的显示是这个具体值,mode是EXACTLY;
(2)子view是MATCH_PARENT,那么子view的显示是viewGroup的size,mode是EXACTLY;
(3)子view是wrap_content,那么子view显示viewGroup的size,mode是AT_MOST。

2、当viewGroup是MeasureSpec.AT_MOST:

(1)子view是具体值,例如200dp,那么子view显示这个具体值,mode是EXACTLY;
(2)子view是MATCH_PARENT,那么子view显示是viewGroup的size,mode是AT_MOST;
(3)子view是wrap_content,那么子view显示是viewGroup的size,mode是AT_MOST。

3、当ViewGroup是MeasureSpec.UNSPECIFIED:
(1)子view是具体值,例如200dp,那么子view显示这个具体值,mode为EXACTLY;
(2)子view是MATCH_PARENT,子view显示是viewGroup的size,mode是UNSPECIFIED;
(3)子view是wrap_content,那么子view显示viewGroup的size,mode是UNSPECIFIED。

精彩评论(0)

0 0 举报