View 的绘制流程分为三步:measure(测量)、layout(布局)、draw(绘制)
- measuer:根据父View船体的MeasureSpec进行计算大小
- layout:根据measure 子View 所得的布局大小和布局参数,确定Veiw的位置
- draw:把view对象绘制到屏幕上
大致流程如下:
measure
iew 测量流程是父 View 先测量子 View,等子 View 测量完了,再来测量自己
measure 主要功能就是测量设置 View 的大小。该方法是 final 类型,子类不能覆盖,在方法里面会调用 onMeasure(),我们可以复写 onMeasure() 方法去测量设置 View 的大小
layout()
View 的 layout 的方法也是非常长。大致作用就是设置 View 的在父 View 的位置,然后判断位置是否发生变化,是否需要重新调用排版布局,如果是需要重新布局则用了 onLayout()方法。
在OnLayout 方法中,View 里面是一个空实现,而 ViewGroup 则是一个抽象方法。为什么这么设计呢?因为onLayout中主要就是为了给遍历View然后进行排版布局,分别设置View在父View中的位置。既然如此,那么View的意义就不大了,而ViewGruo 必须实现,不然没法对子View进行布局。那么如何对 View 进行排版呢?
draw()
- 第一步:drawBackground(canvas): 作用就是绘制 View 的背景。
- 第三步:onDraw(canvas) :绘制 View 的内容。View 的内容是根据自己需求自己绘制的,所以方法是一个空方法,View的继承类自己复写实现绘制内容。
- 第三步:dispatchDraw(canvas):遍历子View进行绘制内容。在 View 里面是一个空实现,ViewGroup 里面才会有实现。在自定义 ViewGroup 一般不用复写这个方法,因为它在里面的实现帮我们实现了子 View 的绘制过程,基本满足需求。
- 第四步:onDrawForeground(canvas):对前景色跟滚动条进行绘制。
- 第五步:drawDefaultFocusHighlight(canvas):绘制默认焦点高亮
绘制发起入口
在介绍飞起绘制入口之前,我们先了解Window ViewRootImpl DecorView之前的联系。一个activity包含一个window window是一个抽象基类,是activity和整个view系统交互的接口,只有一个子类实现phonewindow,提供了一系列窗口的方法,比如设置背景,标题等。
一个phonewindow对应一个DecorView和一个ViewRootImpl,DecorView是ViewTree里面的顶层布局,是继承于FrameLayout 包含两个子View 一个id = statusBarBackground的View和 LinearLayout,LinearLayout里面包含title跟content title就是平时用的TitleBar或者ActionBar,content也就是FrameLayout ,activity通过设置setContent 加载布局的时候加载到这个view上面,ViewRootImpl就是简历DecorView和window之前的联系。
网友评论