您的位置:首页 > 移动开发 > Android开发

android自定义View探索5(onMeasure深入分析二LayoutParams)

2017-06-19 15:11 411 查看

前言:

android自定义View探索3(onMeasure深入分析一) 这篇文章中我介绍了onMeasure的基础知识,其中View的测量宽高是由父控件的MeasureSpec和View自身的

LayoutParams共同决定的,那么LayoutParams是什么?MeasureSpec与LayoutParams的对应关系是什么?

一.LayoutParams简介:

     

1.来看看官方文档的概述:

LayoutParams are used by views to tell their parents how they want to be laid out. See ViewGroup
Layout Attributes for a list of all child view attributes that this class supports.

The base LayoutParams class just describes how big the view wants to be for both width and height.
For each dimension, it can specify one of:

FILL_PARENT (renamed MATCH_PARENT in API Level 8 and higher), which means that the view wants to
be as big as its parent (minus padding)

WRAP_CONTENT, which means that the view wants to be just big enough to enclose its content (plus padding)
an exact number

There are subclasses of LayoutParams for different subclasses of ViewGroup. For example, AbsoluteLayout
has its own subclass of LayoutParams which adds an X and Y value.


我把官方的概述分解了:

(1).在子视图中用LayoutParams告诉父视图它们要如何设置(比如设置layout_width、layout_height、layout_gravity等等...凡是带layout的都是)

(2).凡是以layout开头的属性,都是用于告诉父容器的。

(3).基本的LayoutParams只是像父视图传递高度和宽度大小。

MATCH_PARENT:

在api Level 8 之前用的是FILL_PARENT,那么MATCH_PARENT与FILL_PARENT有什么区别?为什么FILL_PARENT不用了?

先來看第一个问题,MATCH_PARENT于FILL_PARENT有什么区别?

我们来看看源码?

public static class LayoutParams {
/**
* Special value for the height or width requested by a View.
* FILL_PARENT means that the view wants to be as big as its parent,
* minus the parent's padding, if any. This value is deprecated
* starting in API Level 8 and replaced by {@link #MATCH_PARENT}.
*/
@SuppressWarnings({"UnusedDeclaration"})
@Deprecated
public static final int FILL_PARENT = -1;

/**
* Special value for the height or width requested by a View.
* MATCH_PARENT means that the view wants to be as big as its parent,
* minus the parent's padding, if any. Introduced in API Level 8.
*/
public static final int MATCH_PARENT = -1;

/**
* Special value for the height or width requested by a View.
* WRAP_CONTENT means that the view wants to be just large enough to fit
* its own internal content, taking its own padding into account.
*/
public static final int WRAP_CONTENT = -2;


它们除了字面上不同外,最终结果两个没有任何区别。

第二个问题,为什么FILL_PARENT不用了?

既然功能上完全相同,那么只能从字面去寻找答案了?FILL_PARENT,填满整个屏幕,显然跟实际功能不相符的。为了更严谨我们还是写一个布局测试测试,

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>

<Button
android:id="@+id/button2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:text="Button" />

<Button
android:id="@+id/button"
android:layout_width="fill_parent"
android:layout_height="200dp"
android:text="Test1" />

</LinearLayout>


运行截图



我们的button2设置了FILL_PARENT但是它并没有填充整个屏幕,故FILL_PARENT是不严谨不准确的,而MATCH_PARENT表示塞满容器,塞的意思就是有多

少空间,占用多少空间,与实际效果更符合。

WRAP_CONTENT:

根据内容自适应大小

(4).ViewGroup的每一种子类实现不同的布局方式都有其对应的参数设置,AbsoluteLayout、ViewPager都有其对应的子LayoutParams并且有独特的参数。

2.来看看LayoutParams的继承结构

java.lang.Object
↳	android.view.ViewGroup.LayoutParams


二 .MeasureSpec和LayoutParams的对应关系

android自定义View探索3(onMeasure深入分析一)那篇文章中已经说了,“系统会将View的LayoutParams跟据父容器所施加的规则转换成对应的MeasureSpec”,

LayoutParams是怎么转化成MeasureSpec?

我们可以把它设置成以下几步

1.给View设置LayoutParams

2.在View测量的时候,系统会将LayoutParams在父容器的约束转换成对应的MeasureSpec

3.根据这个MeasureSpec来确定View测量后的宽/高。

注意点:

1 MeasureSpec不是唯一由LayoutParams决定的,LayoutParams需要和父容器一起才能决定MeasureSpec。

2 对于顶级View(即DecorView)和普通View来说,MeasureSpec的转换过程略有不同。

DecorView:

MeasureSpec由窗口的尺寸和其自身的LayoutParams来共同决定;

普通View:

MeasureSpec由父容器的MeasureSpec和自身的LayoutParams来共同决定。

总结:第一步确定MeasuSpec,MeasuSpec确定后,onMeasure就可以确定View的测量宽/高。

那么MeasuSpec由哪系因素决定呢?

第一  SpecSize所指定的值.

第二 SpecMode所的取值模式

第三 LayoutParams和父容器,然后就是它的顶级View和普通View的转换模式


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息