返回

Android View 测量详解

Android

概述

Android View 测量是确定 View 大小和位置的过程。它由父容器(ViewGroup)调用,以确定其子 View 的大小和位置。测量结果由 View 的 layout() 方法使用,以将 View 放置在正确的位置。

测量规范

测量规范是一个包含两个值的结构,用于指定 View 的测量约束。这两个值分别是:

  • 宽度规范 (widthMeasureSpec) :指定 View 在水平方向上可以使用的最大宽度。
  • 高度规范 (heightMeasureSpec) :指定 View 在垂直方向上可以使用的最大高度。

每个规范值都由两个标志位和一个数字组成:

  • 标志位 (specMode) :指定 View 在该方向上的测量模式。它可以是以下三种之一:
    • UNSPECIFIED :View 在该方向上没有约束,可以是任何大小。
    • EXACTLY :View 在该方向上的大小被精确指定,必须是指定的大小。
    • AT_MOST :View 在该方向上的大小不能超过指定的大小,但可以小于指定的大小。
  • 数字 (specSize) :指定 View 在该方向上可以使用的最大值。

测量流程

测量流程如下:

  1. 父容器调用子 View 的 measure() 方法。
  2. 子 View 根据测量规范和自己的测量规则计算其大小。
  3. 子 View 将其计算的大小返回给父容器。
  4. 父容器使用子 View 返回的大小来确定子 View 的位置。

测量模式

测量模式有三种:UNSPECIFIED、EXACTLY 和 AT_MOST。

  • UNSPECIFIED :View 在该方向上没有约束,可以是任何大小。这种模式通常用于 View 的根布局。
  • EXACTLY :View 在该方向上的大小被精确指定,必须是指定的大小。这种模式通常用于 View 的子布局。
  • AT_MOST :View 在该方向上的大小不能超过指定的大小,但可以小于指定的大小。这种模式通常用于 View 的子布局,以确保子 View 的大小不超过父容器的大小。

测量示例

下面是一个测量示例,展示了如何测量一个 FrameLayout。

public class MyFrameLayout extends FrameLayout {

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // 获取子 View 的个数
        int childCount = getChildCount();

        // 计算 FrameLayout 的宽度和高度
        int width = 0;
        int height = 0;

        // 遍历子 View,并计算 FrameLayout 的宽度和高度
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);

            // 测量子 View
            measureChild(child, widthMeasureSpec, heightMeasureSpec);

            // 计算 FrameLayout 的宽度和高度
            width = Math.max(width, child.getMeasuredWidth());
            height = Math.max(height, child.getMeasuredHeight());
        }

        // 设置 FrameLayout 的宽度和高度
        setMeasuredDimension(width, height);
    }
}

在上面的示例中,FrameLayout 的宽度和高度是根据子 View 的宽度和高度计算的。FrameLayout 的宽度是子 View 中最宽的子 View 的宽度,FrameLayout 的高度是子 View 中最高子 View 的高度。