[Android] 如何计算View的Size

** 注:本文参考连接How Android caculates view sizeandroid

本文例子以下所示:ide

<LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="20dp" />

</LinearLayout>

过程

计算view大小的过程能够分为如下几个步骤:post

  1. 肯定view想要的size(LayoutParams)
  2. 肯定parent view的状况(MeasureSpec)
  3. 在parent view的限制下,根据view的LayoutParams,肯定view的大小

参数

LayoutParams

LayoutParams用于view表示想要的size的模式。有如下三种:字体

  1. FILL_PARENT / MATCH_PARENT (-1)
    view的size和parent view的size同样大
  2. WRAP_CONTENT(-2)
    view的size仅包裹其内容便可
  3. 指定的值(>0)
    view的size为指定的size大小

MeasureSpec

MeasureSpec表示当前view的“约束”(在onMeasure中传入)。约束含模式mode和数值size,当前view根据mode来决定如何看待其中的size。.net

mode

mode有三种,以下所示:code

  1. UNSPECIFIED
    对当前view的size没有约束
  2. EXACTLY
    当前view的bounds(能够理解成“可使用的范围”)为肯定的size,也能够理解成parent view但愿当前view(有强制的意味)使用给定的size
  3. AT_MOST
    当前view的大小不可超过指定的size

能够利用MeasureSpec的getMode取出具体值.ci

size

size为8个byte的int值,mode放在前2个bit中。这里能够利用MeasureSpec的getSize取出size的具体值。get

onMeasure过程

view经过onMeasure肯定本身的大小。肯定本身的大小时,须要的东西有:it

  1. 约束MeasureSpec
  2. 本身的LayoutParams
  3. 若是有child view,那么须要获取child view的大小

最终肯定当前view的size分别为:io

  1. measureWidth
  2. measureHeight

single view

之前面例子中的TextView为例,其onMeasure中传入的MeasureSpec为:

  1. Width
    mode:EXACTLY size:parentContentWidth(LinearLayout的宽-padding)
  2. Height
    mode:AT_MOST size:parentContentHeight(LinearLayout的高-padding)

注:这里先不解释为何MeasureSpec是这样的。

TextView的LayoutParams为:

  1. Width
    MATCH_PARENT
  2. Height
    WRAP_CONTENT

而后TextView根据约束和LayoutParams肯定本身的大小,包括但不限于如下过程:

  1. 设置宽度为parentContentWidth,考虑margin肯定字符可用范围
  2. 根据字符高度和字体设置(根据是否超过parentContentWidth肯定是否换行)等计算字符所占的高度(没有限制)。
  3. 设置measureWidth和measureHeight

ViewGroup

之前面例子中的LinearLayout为例,假设该LinearLayout为Activity中的root layout其onMeasure中传入的MeasureSpec为:

  1. Width
    mode:EXACTLY size:parentContentWidth(LinearLayout的parent view的宽-padding)
  2. Height
    mode:AT_MOST size:parentContentHeight(LinearLayout的parent view的高-padding)

RelativeLayout的LayoutParams为:

  1. Width
    MATCH_PARENT
  2. Height
    WRAP_CONTENT
  3. Orientation
    vertical

而后LinearLayout根据约束和LayoutParams肯定本身的大小,包括但不限于如下过程:

  1. 肯定child view的排列方式
  2. 肯定TextView的size
  3. 肯定ImageView的size
  4. 根据自身的设置,设置measureWidth和measureHeight

要肯定child view的size,就要调用child view的onMeasure,传入合适的MeasureSpec,代表parent view对child的约束。

根据parent view的不一样module和child view的不一样LayoutParams,有以下规则:

  1. 当parent view的mode是EXACTLY时:

    child layout mode size
    exact size EXACTLY childSize Child wants a specific size.
    MATCH_PARENT EXACTLY parentContentSize Child wants to be parent's size.
    WRAP_CONTENT AT_MOST parentContentSize Child wants to determine its own size. It can not be bigger than parent.
  2. 当parent view的mode是AT_MOST时:

    child layout mode size
    exact size EXACTLY childSize Child wants a specific size
    MATCH_PARENT AT_MOST parentContentSize Child wants to be parent's size, but parent's size is not fixed. Constrain child to not be bigger than parent.
    WRAP_CONTENT AT_MOST parentContentSize Child wants to determine its own size, but it can not be bigger than parent.
  3. 当parent view的mode是UNSPECIFIED时:

    child layout mode size
    exact size EXACTLY childSize Child wants a specific size.
    MATCH_PARENT UNSPECIFIED can not decide yet Child wants to be parent's size. Child will decide its own size later.
    WRAP_CONTENT UNSPECIFIED can not decide yet Child wants to be its own size. Child will decide its own size later.

以例子中的TextView为例:

  1. LinearLayout的width mode为EXACTLY,TextView的width layout param为MATCH_PARENT
  2. LinearLayout的height mode为AT_MOST,TextView的height layout param为WRAP_CONTENT

因此TextView的onMeasure会被传入:

  1. Width
    mode:EXACTLY size:parentContentWidth(LinearLayout的宽-padding)
  2. Height
    mode:AT_MOST size:parentContentHeight(LinearLayout的高-padding)

TextView能够根据上述约束计算本身的大小。ImageView同理。最后LinearLayout根据ImageView和TextView的大小计算本身的大小。注意这里没有weight的设置,因此onMeasure只运行一次。

如上述有错,请留言告知。

相关文章
相关标签/搜索