美文网首页
Android 开发艺术探索笔记(十一) 之 View 的工作原

Android 开发艺术探索笔记(十一) 之 View 的工作原

作者: innovatorCL | 来源:发表于2018-03-17 10:16 被阅读24次

    1、ViewRoot 和 DecorView

    • ViewRoot 对应于 ViewRootImpl 类,是连接 WindowManagerDecorView 的纽带,View 的 measure,layout,draw 都是通过 ViewRoot 来完成的。
    • View 的三大流程:measure 过程决定了 View 的宽/高,measure 完成后,可以通过 getMeasuredWidth()/getMeasuredHeight() 获取 View 测量后的宽/高,这个宽高几乎就是 View 最终的宽/高了,除了特殊情况之外;layout 过程决定了 View 的四个顶点的坐标和实际的宽/高,完成后可以通过 getTop()getLeft()getRight()getBottom() 获取四个顶点的坐标,还可以通过 getWidth()getHeight() 获取 View 的最终的宽/高;draw 过程就决定了 View 的显示,只有 draw() 完成才能将 View 的内容呈现在屏幕上。

    • DecorView 其实是一个 FrameLayout,里面包含一个 LinearLayout,这个 LinearLayout 包含两个子View,一个是 Titlebar,另一个是 id 为 android.R.id.content 的 FrameLayout,可以通过 ViewGroup content = (ViewGroup) findViewById(android.R.id.content);来获取这个 contentView,然后通过 content.getChild(0) 来获取我们设置进去的 View。

    2、MeasureSpec

    MeasureSpec 代表一个 32 位 int 值,高 2 位代表 SpecMode(测量模式),低 30 位代表 SpecSize(某种测量模式下的规格大小)。

    MeasureSpec 有 3 类:

    • UNSPECIFIED:父容器不对 View 做任何限制,要多大给多大。这种情况一般用于系统内部,表示一种测量状态。

    • EXACTLY:父容器已经检测出 View 所需要的大小,View 的大小就是 SpecSize 指定的值。这种情况对应于 LayoutParams 的 match_parent 和具体数值两种情况。

    • AT_MOST:父容器指定了一个可用的大小 SpecSize,View 最大不能超过这个 SpecSize 的值。这种情况对应于 LayoutParams 的 wrap_content。

    注意:MeasureSpec 不是由该 View 的 LayoutParams 唯一决定的,而是在父容器的约束下(父容器的 MeasureSpec),将该 View 的 LayoutParams 转换成对应的 MeasureSpec,从而决定该 View 的测量后(onMeasure())的宽/高。

    普通 View 的 MeasureSpec 的确定方法:

    • 当 View 的 LayoutParam 是固定的宽/高的模式时,不管父容器的 MeasureSpec 是什么,View 的 MeasureSpec 都是 EXACTLY(精确模式)并且其大小遵循 LayoutParams 的大小

    • 当 View 的宽/高是 match_parent 时,如果父容器的 MeasureSpec 是精准模式,View 的 MeasureSpec 也是 EXACTLY(精确模式)并且其大小就是父容器的剩余空间;如果父容器是 AT_MOST(最大模式),那么View 的 MeasureSpec 也是 AT_MOST(最大模式)并且其大小不会超过父容器的剩余空间

    • 当 View 的宽/高是 wrap_content 时,不管父容器的 MeasureSpec 是精准模式还是最大模式,View 的 MeasureSpec 都是 AT_MOST(最大模式)并且其大小不会超过父容器的剩余空间

    3、View 的工作原理

    • measure 过程

      measure 过程分两种情况,第一种是只是一个原始的 View ,那么通过 measure 方法就完成了其测量过程;如果是一个 ViewGroup,除了完成自己的测量过程外,还要遍历去调用所有子元素的 measure 方法,各个子元素再递归执行这个流程。

      获取 View 测量后的宽/高的方法:

      • 1.Activity/View # onWindowFocusChanged

      • 2.view.post(runnable)

      • 3.ViewTreeObserver

      • 4.view.measure(int widthMeasureSpec,int heightMeasureSpec)

    • layout 过程

      layout 是 ViewGroup 用来确定子元素的位置的,当 ViewGroup 的位置被确定后,在 onLayout()中会遍历所有子元素并调用其 layout 方法,在 layout 方法中 onLayout() 被调用。

      父容器确定了自己的位置,即四个顶点的坐标之后,确定子元素的位置。

    • draw 过程

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

    相关文章

      网友评论

          本文标题:Android 开发艺术探索笔记(十一) 之 View 的工作原

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