读书人

Android中measure过程、WRAP_CONTENT详

发布时间: 2012-10-13 11:38:17 作者: rapoo

Android中measure过程、WRAP_CONTENT详解以及xml布局文件解析流程浅析(上)

本文原创, 转载请注明出处:http://blog.csdn.net/qinjuning




在之前一篇博文中<< Android中View绘制流程以及invalidate()等相关方法分析>>,简单的阐述 了Android View

绘制流程的三个步骤,即:

1、 measure过程 --- 测量过程

2、layout 过程 --- 布局过程
3、draw 过程 --- 绘制过程

要想对Android 中View这块深入理解,对这三个步骤地学习是必不可少的 。

今天,我着重讲解下如下三个内容:

1、 measure过程

2、WRAP_CONTENT、MATCH_PARENT/FILL_PARENT属性的原理说明

3、xml布局文件解析成View树的流程分析。


希望对大家能有帮助。- - 分析版本基于Android 2.3



1、WRAP_CONTENT、MATCH_PARENT/FILL_PARENT

初入Android殿堂的同学们,对这三个属性一定又爱又恨。爱的是使用起来挺爽地---照葫芦画瓢即可,恨的

却是时常混淆这几个属性地意义,需要三思而后行。在带着大家重温下这几个属性的用法吧(希望我没有嗦)。


这三个属性都用来适应视图的水平或垂直大小,一个以视图的内容或尺寸为基础的布局比精确地指定视图范围

更加方便。

① fill_parent

设置一个视图的布局为fill_parent将强制性地使视图扩展至父元素大小。

② match_parent

Android 中match_parent和fill_parent意思一样,但match_parent更贴切,于是从2.2开始两个词都可以

用,但2.3版本后建议使用match_parent。

③ wrap_content

自适应大小,强制性地使视图扩展以便显示其全部内容。以TextView和ImageView控件为例,设置为

wrap_content将完整显示其内部的文本和图像。布局元素将根据内容更改大小。

可不要重复造轮子,以上摘自<<Android fill_parent、wrap_content和match_parent的区别>>。


当然,我们可以设置View的确切宽高,而不是由以上属性指定。


该类图是在太庞大了,大家有兴趣的去看看Android API吧。


前面我们说过,每个View都包含一个ViewGroup.LayoutParams类或者其派生类,下面我们的疑问是Android框架

中时如何为View设置其LayoutParams属性的。


有两种方法会设置View的LayoutParams属性:

1、直接添加子View时,常见于如下几种方法:ViewGroup.java

inflate           public View inflate (int resource, ViewGroup root)

public View inflate (int resource, ViewGroup root, boolean attachToRoot)

这三个类主要迷惑之处在于地三个参数attachToRoot,即是否将该View树添加到root中去。具体可看这篇博客:

<<关于inflate的第3个参数>>

当然还有LayoutInflater的inflate()的其他重载方法,大家可以自行了解下。

我利用下面的例子给大家走走这个流程 :

public class TypedArray {.../**     * Special version of {@link #getDimensionPixelSize} for retrieving     * {@link android.view.ViewGroup}'s layout_width and layout_height     * attributes.  This is only here for performance reasons; applications     * should use {@link #getDimensionPixelSize}.     *      * @param index Index of the attribute to retrieve.     * @param name Textual name of attribute for error reporting.     *      * @return Attribute dimension value multiplied by the appropriate      * metric and truncated to integer pixels.     */    public int getLayoutDimension(int index, String name) {        index *= AssetManager.STYLE_NUM_ENTRIES;        final int[] data = mData;        //获得属性对应的标识符 , Identifies,目前还没有仔细研究相关类。        final int type = data[index+AssetManager.STYLE_TYPE];        if (type >= TypedValue.TYPE_FIRST_INT                && type <= TypedValue.TYPE_LAST_INT) {            return data[index+AssetManager.STYLE_DATA];        } else if (type == TypedValue.TYPE_DIMENSION) { //类型为dimension类型            return TypedValue.complexToDimensionPixelSize(                data[index+AssetManager.STYLE_DATA], mResources.mMetrics);        }        //没有提供layout_weight和layout_height会来到此处 ,这儿会报异常!        //因此布局文件中的View包括自定义View必须加上属性layout_weight和layout_height。        throw new RuntimeException(getPositionDescription()                + ": You must supply a " + name + " attribute.");    }...}

从上面得知, 我们将View的AttributeSet属性传递给generateLayoutParams()方法,让其构建合适地

LayoutParams对象,并且初始化属性值weight和height。同时我们也得知 布局文件中的View包括自定义View

必须加上属性layout_weight和layout_height,否则会报异常。


Step 3 主要做了如下事情:
首先,获得了了布局文件地root View,即布局文件中最顶层的View。

其次,通过递归调用,我们形成了整个View树以及设置了每个View的LayoutParams对象。


总结:通过对布局文件的解析流程的学习,也就是转换为View树的过程,我们明白了解析过程的个中奥妙,以及

设置ViewLayoutParams对象的过程。但是,我们这儿只是简单的浮光掠影,更深层次的内容希望大家能深入学习。




本来是准备接下去往下写的,但无奈贴出来的代码太多,文章有点长而且自己也有点凌乱了,因此决定做两篇

博客发表吧。下篇内容包括如下方面:

1、MeasureSpec类说明 ;

2、measure过程中如何正确设置每个View的长宽 ;

3、UI框架正确设置顶层View的LayoutParams对象,对Activity而言,顶层View则是DecorView,

其他的皆是普通View了。











读书人网 >XML SOAP

热点推荐