View 的工作原理

栏目: IOS · Android · 发布时间: 7年前

内容简介:理解 View 的工作原理,熟悉自定义 View 的各种套路。本章节配套源码

理解 View 的工作原理,熟悉自定义 View 的各种套路。

1. ViewRoot 和 DecorView

  1. ViewRoot 对应于 ViewRootImpl 类,它是连接 WindowManager 和DecorView 的纽带。
  2. View 的绘制流程是从 ViewRoot 的 performtraversals 方法开始的:
    View 的工作原理
  3. measure 的过程决定了 View 的宽高,完成后可以通过 getMeasuredWidth 和 getMeasuredHeight 获取。
  4. layout 的过程决定了 View 的四个顶点的坐标和实际宽高,完成后可以通过 getTopgetBottomgetLeftgetRight 获取。
  5. draw 的过程决定了 View 的显示,完成后才能呈现在屏幕上。
  6. 在 Activity 中通过 setContentView 的布局可以通过以下方式获取到:
    ViewGroup content = findViewById(android.R.id.content);
    

2. MeasureSpec

  1. MeasureSpec 和父容器决定了 View 的尺寸规格。
  2. MeasureSpec 是一个 32 位的 int 值,高 2 位代表 SpecMode ,低 30 位代表 SpecSize

    > int mode = MeasureSpec.getMode(spec);
    > int size = MeasureSpec.getSize(spec);
    >
    
  3. SpecMode 有三类:

    • UNSPECIFIED :父容器不对 View 有任何限制,要多大给多大。
    • EXACTLY :父容器已经检测出 View 所需的精确代销,这时 View 的最终大小就是 SpecSize 的值,它对应于 LayoutParams 中的 match_parent 或具体大小数值。
    • AT_MOST :父容器指定了一个大小 SpecSize,View 不能大于这个值,最终大小取决于 View 的具体实现,它对应于 LayoutParams 中的 wrap_content。
  4. 我们在给 View 设置 LayoutParams 后,系统会在父容器的约束下将 LayoutParams 转换成对应的 MeasureSpec。
    • 顶级 DecorView,其 MeasureSpec 由窗口尺寸和自身 LayoutParams 决定。
    • 普通 View,其 MeasureSpec 由父容器的 MeasureSpec 和自身 LayoutParams 决定。
  5. 普通 View 的 MeasureSpec 创建规则:
childLayoutParams \ parentSpecMode EXACTLY AT_MOST UNSPECIFIED
dp/px EXACTLY
childSize
EXACTLY
childSize
EXACTLY
childSize
match_parent EXACTLY
parentSize
AT_MOST
parentSize
UNSPECIFIED
0
wrap_content AT_MOST
parentSize
AT_MOST
parentSize
UNSPECIFIED
0

3. View 的工作流程

3.1 measure 过程

  1. 分两种情况,如果是一个原始 View,通过 measure 方法就完成了测量过程;如果是 ViewGroup,除了完成自己的测量,还要遍历子元素的 measure 方法。
  2. 直接继承 View 的自定义控件需要重写 onMeasure 方法并设置 wrap_content 时的自身大小,否则在布局中使用 wrap_content 时就相当于使用 match_parent;
  3. ViewGroup 是一个抽象类,并没有定义其具体的测量过程,但它提供了一个 measureChildren(int widthMeasureSpec, int heightMeasureSpec) 的方法来测量子元素,该方法里循环调用 measureChild(child, widthMeasureSpec, heightMeasureSpec) 方法, measureChild 的思想就是取出元素的 LayoutParams,然后通过 getChildMeasureSpec 方法创建子元素的 MeasureSpec,最后将 MeasureSpec 传递给 View 的 measure 方法来进行测量。
  4. 简化版的流程图如下:
    View 的工作原理
  5. 由于在一些极端情况下,系统要在多次 measure 后才能确定测量的结果,所以在 onMeasure 中拿到的宽高可能不准确,推荐在 onLayout 中获取。
  6. 准确获取 View 宽高的四种方式:

    • Activity/View#onWindowFocusChanged
    • view.post(runnable)
    • ViewTreeObserver

      ...
      ViewTreeObserver observer = view.getViewTreeObserver();
      observer.addOnGlobalLayoutListener
      ...
      
    • view.measure(int widthMeasureSpec, int heightMeasureSpec)

3.2 layout 过程

  1. View 的 onLayout 方法为空实现,而 ViewGroup 继承自 View 也没有实现该方法,所以 onLayout 具体实现由父容器的特性决定,比如 LinearLayout。
  2. 简易的流程图如下:
    View 的工作原理
  3. 在 View 的默认实现中,View 的测量宽高和最终宽高是相等的,只不过测量宽高形成于 measure 过程,而最终宽高形成于 layout 过程,两者赋值时机不同。

3.3 draw 过程

  1. draw 的绘制过程遵循如下几步:
    background.draw(canvas)
    onDraw
    dispatchDraw
    onDrawScrollBars
    
  2. ViewGroup 默认启用绘制优化标记位,如果 ViewGroup 需要通过 onDraw 来绘制内容,我们可以通过 setWillNotDraw(false); 来关闭该标记位。

4. 自定义 View

  1. 自定义 View 大体可以分为四类:
    1. 继承 View 重写 onDraw 方法
    2. 继承 ViewGroup 派生特殊的 Layout
    3. 继承特定的 View(比如 TextView)
    4. 继承特定的 ViewGroup(比如 LinearLayout)
  2. 自定义 View 须知:
    post
    View#onDetachedFromWindow
    

本章节配套源码 戳我


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web Data Mining

Web Data Mining

Bing Liu / Springer / 2011-6-26 / CAD 61.50

Web mining aims to discover useful information and knowledge from Web hyperlinks, page contents, and usage data. Although Web mining uses many conventional data mining techniques, it is not purely an ......一起来看看 《Web Data Mining》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

随机密码生成器
随机密码生成器

多种字符组合密码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具