Android基础知识四(View类和ViewGroup类、View绘制流程机制)

来源:互联网 发布:手机上开淘宝店怎么开 编辑:程序博客网 时间:2024/06/16 05:26

View类和ViewGroup类、View绘制流程机制可以会用。但是如果不系统的知道,到底是什么、怎么流程,总觉得心虚呀~

View类介绍

绘制的流程:

(1)绘制按照视图树的顺序进行。视图绘制时会先绘制子控件。如果视图的背景可见,绘图会在调用onDraw函数之间绘制背景。

(2)强制重绘,可以使用invalidate()。

事件的基本处理流程:

(1)事件分配给相应视图,视图处理它,并通知相关监听器。

(2)操作过程中如果发生视图的尺寸变化,则该视图调用requestLayout()方法,请求再次布局。

(3)操作过程中如果发生视图的外观变化,则该视图调用invalidate()方法,请求重绘。

(4)如果requestLayout()和invalidate()有一个被调用,框架会对视图树进行相关的测量、布局和绘制。

焦点处理:

框架处理焦点的转移,来响应用户输入。

成员介绍:

(1)protected ViewParent mParent
用来记录它的父亲,就是我们前面提到的ViewGroup

(2)protected OnClickListener mOnClickListener
mOnClickListener是Click事件的回调接口

(3)public void draw(Canvas canvas)
这个函数用于渲染View和它的孩子,我们不应该在子类对它进行override。

(4)protected void onDraw(Canvas canvas)
我们一般override此函数来实现自己的绘制操作

(5)public final void layout(int l, int t, int r, int b)
此函数用于确定View和其子View的尺寸和位置,它的调用发生在onMeasure之后

(6)protected void onLayout(boolean changed, int left, int top, int right, int bottom)
此函数在layout调用完成后进行,View的子类一般override此函数,并在函数中对每个孩子调用layout方法。

(7)public View getRootView()
此函数用于得到View层次的Top View,即上文提到的DecorView

(8)public final void measure(int widthMeasureSpec, int heightMeasureSpec)
此函数用户找出View的大小,它的参数widhtMeasureSpec、HeightMeasure是其父类传给它的,这2个参数是View找出其大小时的限制条件,起始真正的精确大小是由onMeasure完成的,onMeasure有measure函数调用

(9)protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
此函数测量View并根据其内容来决定View的高和宽,它应该被子类override来实现精确的测量。在onMeasure中我们必须调用View.setMeasureDimension(int,.int)来保存测量得到的大小,高和宽分别被保存在View.mMeasureHeight和View.mMeasureWidth中。

(10)public void invalidate()
此函数将调用onDraw(),强制重绘。

(11)public void requestLayout()
当某些东西发送改变后,当前View层次结构无效了,调用此函数对View的层次结构进行重新布局。

ViewGroup类

(1)ViewGroup类继承于View,它可以包含其它的View,就像一个View的容器,我们可以调用其成员函数addView将View当做孩子加入到ViewGroup中。

(2)我们经常使用的LinearLayout、RelativeLayout等都是ViewGroup的子类,ViewGroup类中有个内部类ViewGroup.LayoutParams,我们经常使用LayoutParams的子类来构造布局参数。

(3)我们也可以定义自己的布局,以方便日后使用和维护,这时我们就需要继承ViewGroup类并重写ViewGroup中的一些方法。

View绘制流程机制

整个View树的绘图流程是在ViewRoot.java类的performTraversal()函数展开的,该函数做的执行过程可简单概括为:

A)根据之前的状态,判断是否需要重新计算视图大小(measure)
B)是否需要重新安置视图的位置(layout)
C)是否需要重绘(draw)
measure过程:
(1)主要作用:为整个View树计算实际的大小,即设置实际的高(对应属性mMeasureHeight和mMeasureWidth),每个View控件的实际宽高都是由父视图和本身视图决定的。
(2)具体的调用链如下:
A)ViewRoot根据对象的属性mView(其类型一般为ViewGroup类型)去计算View树的大小,回调View/ViewGroup对象的onMeasure()方法。
B)设置本View视图的最终大小。
C)如果该View对象是个ViewGroup类型,需要重写该onMeasure()方法,对其子视图进行遍历的measure()过程。
D)整个measure()调用过程就是树形的递归过程。

layout布局过程:
(1)主要作用:根据子视图的大小以及布局参数将View树放到合适的位置上。
(2)具体的调用链:
A)host.layout()开始View树的布局,继而回调给View/ViewGroup类中的layout方法。
B)layout()会设置该View视图位于父视图的坐标轴,即mleft,mright等。
C)如果该View是一个ViewGroup类型,需要遍历每个子视图childView,调用该子视图的方法去设置它的坐标值。

draw过程:
(1)每次发起绘图时,并不会重新绘制每个View树的视图,而只会重新绘制那些需要重绘的视图。
(2)调用流程:
A)绘制该View的背景。
B)为显示渐变框做一些准备。
C)调用onDraw()方法绘制视图本身。(每个View都需要重载该方法,ViewGroup不需要实现该方法)
D)调用dispatchDraw()方法绘制子视图。(如果该View类型不为ViewGroup,不需要重载方法)。
E)绘制滚动条。
F)整个调用链就这样递归下去了。
  在这3个流程当中,ViewGroup只需要实现measure()和layout()过程即可。其最终会直接或间接调用到3个函数,接着这3个函数最终会调用到ViewRoot中的schedulTraversale()方法,该函数然后发起一个异步消息,消息处理中调用performTraverser(0方法对整个View进行遍历。

原创粉丝点击