android view的工作原理(一)

前言:

在界面上Android 提供一套GUI库,里面有很多控件,但是很多时候我们并不满足于系统系统的控件,造成应用界面的同类化比较严重,所以我们需要自定义view,可以实现不同的效果,为了更好的自定义view.还需要掌握View的底层工作原理。例如:view的测量流程。布局流程以及绘制流程,这样我们就能定义自己想要的效果

自定义view有几种固定的类型的。有的直接继承自view和viewGroup.有的选择继承现有的系统控件,

 

1.viewRoot和DecorView

viewRoot对应viewRootImpl类,它是连接windowManager和decorView的纽带,当Activity对象被创建,会将DecorViewt添加到window中,并创建viewRootImpl对象,

并将viewRootImpl和decorView建立连接;

View的绘制流程是从viewRoot的preformTraversals方法开始,经过measure,layout,draw 三个过程最终将一个view绘制出来。

大致画一下流程图(看图说话):

                 preformTraversals 的流程图

根据上图所描述的:performTraversals 会一次调用performMesasure,performLayout,和performDrawa,这三个方法完成了顶级view的mesaure,layout,draw流程,其中在performMeasure中回调用measure方法,在measure方法中又会调用onMeasure方法,在onMeasure方法中则会对所有的子元素进行measure过程,这个时候measure流程就从父容器传递到子元素中,完成了一次measure过程,接着子元素会重复父容器的measure过程,完成整个view树的遍历。同理,perfromLayout和perfromDraw的传递流程是类似的,唯一不同的是perfromDraw传递过程在draw方法中通过dispatchDraw来实现,

Measure过程决定view的宽高,measure完成后,可以通过getMeasuredWidth和getMesauredHeight获取到view的宽高,

Draw过程决定了View的显示,只有draw方法完成后内容才能呈现在屏幕上。

2)DecorView(顶级视图),内部包含了一个竖直方向的LinearLayout,在这个linearLayout有上下两个部分,上边是标题栏,下边是内容栏,同时,通过源码我们可以知道,DecorView其实是一个frameLayout,view事件都先经过DecorView,然后传递到我们的View;(画图更清晰)

           顶级View:DecorView的结构

 

2.自定义view的重要东西(MeasureSpec)

1) MeasureSpec在很大程度上决定了View的尺寸规格。这个过程受父容器的影响,在测量过程中,系统会将view的layoutParmas根据父容器所施加的规格转换为MeasureSpec,然后根据这个MesureSpec进行测量view的宽高。

2) MesaureSpec 是什么?

MeasureSpec 代表的是一个32位的int值,高两位代表SpecMode(测量模式),低20位代表SpecSize(测量大小);

MeasureSpec通过将SpecMode和SpecSize打包成一个int值,避免过对的对象内存分配。一组SpecMode和specSize可以打包为一个MeausreSpec,也可以将MeasureSpec进行解包的形式得到原始的SpecMode和SpecSize,

3)SpecMode的三个类,

1.UNSPECIFIED

父容器不对view有任何限制,要多大有多大,常用于系统内部,表示一种测量状态

2.EXACTLY

父容器已经检测出View的所需要的精确大小,这个时候View的最终大小就是SpecSize所指定的值,(match_parent)

3.AT_MOST

父容器指定一个可用的大小specSize. View的大小不能大于这个值,(wrap_content)

 

3.MeasureSpec和LayoutParams的对应关系

正常情况下我们使用view指定的MesaureSpec来对view进行测量,但是我们可以给View设置LayoutParams,在view测量的时候,系统会将layoutParams在父容器的约束下转换为对应的MeausreSpec。

对于DecorView,其MeasureSpec由父容器的MeasureSpec和自身的LayoutParams来共同决定,

对于普通view,其MeasureSpec由父容器的MeasureSpec和自身的layoutParams来共同决定的。

通过如下代码展示DecorView的MeasureSpec的创建过程:

getRootMeasureSpec的方法实现:

通过上述代码:DecorView的MeasureSpec的产生过程很明确了,具体来说遵守如下规则,根据LayoutParams中的宽高参数划分:

  1. LayoutParams.MATCH_PARENT:精确模式,大小就是窗口的大小。
  2. LayoutParams.WRAP_CONTENT : 最大模式,大小不定,但是不能超过窗口的大小;
  3. 固定大小(比如100dp):精确模式,大小为layoutParams中指定的大小;
  4. 通过表格的形式展现view的MeasureSpec的创建规则:

发布了96 篇原创文章 · 获赞 370 · 访问量 42万+

猜你喜欢

转载自blog.csdn.net/wk_beicai/article/details/89670669