Android进阶之View(二)

作者: 拨云见日aaa | 来源:发表于2019-10-09 09:31 被阅读0次

一、ViewRoot和DecorView

ViewRoot对应的是ViewRootImpl类,它是连接WindowManager和DecorView的桥梁,View的measure,layout,draw都是由ViewRoot完成的。在Activity的线程中,当Activity对象创建后,会将DecorView添加到Window中,同时会创建ViewRootImpl对象,并将ViewRootimpl对象和DecorView建立联系。源码如下:



View的绘制是从ViewRoot的performTraversals开始的,它经过measure,layout,draw三个步骤将view显示出来,measure负责测量View的宽高,layout负责测量View的位置,draw负责将View绘制显示出来。performTraversals的大致流程:



performTraversals依次调用performMeasure,performLayout,performDraw方法,三个方法完成顶级View的绘制,performMeasure方法调用measure,measure又调用onMeasure方法,onMeasure方法中则会对所有的子元素进行measure过程,这个时候measure流程就从父容器中传到子元素中了,如此反复就完成View树的绘制了。其余两个流程与之类似。

DecorView作为顶级View,它包含一个竖直方向的LinearLayout,在这个LinearLayout中含有上下两个部分,上面为标题栏,下面为内容栏。在Activity的setContentView方法中就是将布局加载到内容栏中。内容栏是id为content的FrameLayout。

二、MeasureSpec

MeasureSpec是View的内部类代表一个int值,高两位表示SpecMode,低三十位表示SpecSize。
MeasureSpec将SpecMode和SpecSize包装成一个int值,防止过多的内存分配,其含有打包和解包的方法。
SpecMode有如下三类:

  • EXACTLY:父容器已检测出View所需精确的大小,这个时候View的最终大小就是SpecSize指定的大小,对应的是LayoutParams的match_parent和指定具体大小值两种模式
  • AT_MOST:父容器指定一个可用的大小SpecSize,View的大小不能大于这个值,具体是什么看不同View的实现。它对应于LayoutParams中的wrap_content
  • UNSPECIFIED:父容器不对View有任何限制,要多大给多大,这种情况一般用于系统内部
    普通的View由父容器的MeasureSpec和自身的LayoutParams决定


三、View测量绘制流程

1.measure过程

View的measure过程
View的measure方法是final的不可以被重写,所以直接看onMeasure的实现。



我们看一下getDefaultSize方法实现



这个方法会根据不同的mode返回不同的size
再看一下getSuggestedMinimumWidth方法

此方法会查看背景是否为空,若为空则返回mMinHeight否则返回mMinHeight和背景高度的最大值。(mMinHeight对应属性minHeight)
继承View需要自己设置当wrap_content模式下的宽高

ViewGroup的measure过程
对于ViewGroup,除了完成自己的measure过程,还需要遍历完成子元素的measure过程,由于ViewGroup是抽象类,因此它没有重写onMeasure方法,但是它提供了一个measureChildren的方法。




measureChildren方法遍历子元素,然后调用measureChild方法



measureChild就是抽取子元素的LayoutParams和自己的MeasureSpec构成子元素的MeasureSpec
因为ViewGroup的onMeasure需要子类去实现,因为不同的Layout有不同的布局特性。
借用一下厘米姑娘的图
借用一下厘米姑娘的图
2. layout过程

首先顶级View会调用layout,子元素会通过setFrame确定四个顶点位置,接着调用onLayout,父容器确定子元素的位置。这个方法没有具体实现,ViewGroup有不同的布局特性。


借用一下厘米姑娘的图
3.draw过程

(1)绘制背景 background.draw
(2)绘制自己 onDraw
(3)绘制children dispatchDraw
(4) 绘制装饰 onDrawScrollBars

四、自定义View

1.自定义View的分类
  • 继承View重写OnDraw方法
  • 继承ViewGroup派生特殊的Layout
  • 继承特定的View(Text View)
  • 继承特定的ViewGroup(LinearLayout)
2.自定义须知
  • 让Viwe支持wrap_content
  • 如果有必要,让你的View支持Padding
  • 尽量在View中使用Handler
  • View中如果有线程或者动画需要及时停止(在onDetachedFromWindow)
  • View带有滑动嵌套时需要处理好滑动冲突

相关文章

网友评论

    本文标题:Android进阶之View(二)

    本文链接:https://www.haomeiwen.com/subject/hidipctx.html