博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
通过源码分析View的测量
阅读量:6939 次
发布时间:2019-06-27

本文共 3699 字,大约阅读时间需要 12 分钟。

 

要理解View的测量,首先要了解MeasureSpec,系统在测量view的宽高时,要先确定MeasureSpec。

MeasureSpec(32为int值)由两部分组成:

SpecMode(高2位):测量模式。

SpecSize(低30位):某种测量模式下的规格大小。

 

SpecMode有3类:

UNSPECIFIED: 父容器不对view做大小限制,一般用于系统内部,表示一种测量状态。

EXACTLY:精确模式。对应于:LayoutPrams中的match_parent和具体数值。

AT_MOST:最大值模式。对应于LayoutParam中的wrap_content模式。

 

接下来我们看看View的onMeasure方法:

/**     * 

* Measure the view and its content to determine the measured width and the * measured height. This method is invoked by {

@link #measure(int, int)} and * should be overridden by subclasses to provide accurate and efficient * measurement of their contents. *

*protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); }

该方法是由measure来调用的,view宽高的测量值最终是通过setMeasuredDimension来设置,具体实现不去深究。

我们看看getDefaultSize方法:

/**     * Utility to return a default size. Uses the supplied size if the     * MeasureSpec imposed no constraints. Will get larger if allowed     * by the MeasureSpec.     *     * @param size Default size for this view     * @param measureSpec Constraints imposed by the parent     * @return The size this view should be.     */    public static int getDefaultSize(int size, int measureSpec) {        int result = size;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize = MeasureSpec.getSize(measureSpec);        switch (specMode) {        case MeasureSpec.UNSPECIFIED:            result = size;            break;        case MeasureSpec.AT_MOST:        case MeasureSpec.EXACTLY:            result = specSize;            break;        }        return result;    }

 

先从MeasureSpec中获取的测量模式specMode和该模式下的大小specSize,然后对测量模式进行判断,如果是UNSPECIFIED,那么结果就是参数size,对于这个size是什么等会讨论。如果是AT_MOST和EXACTLY,那么结果就是view测量后的大小specSize。

那么这个参数size到底是什么呢?它是由实参getSuggestedMinimumWidth()和getSuggestedMinimumHeight()传下来的,我们进去getSuggestedMinimumWidth()看看。

/**     * Returns the suggested minimum width that the view should use. This     * returns the maximum of the view's minimum width)     * and the background's minimum width     *  ({
@link android.graphics.drawable.Drawable#getMinimumWidth()}). *

* When being used in {

@link #onMeasure(int, int)}, the caller should still * ensure the returned width is within the requirements of the parent. * * @return The suggested minimum width of the view. */ protected int getSuggestedMinimumWidth() { return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth()); }

 

从代码我们可以看出如果该view设置了背景,那么就返回max(mMinWidth, mBackground.getMinimumWidth()),否则返回mMinWidth。

mMinWidth是什么呢?它是对应android:minWidth这个属性的值,若是不指定,那么默认为0.

max(mMinWidth, mBackground.getMinimumWidth()):返回mMinWidth和mBackground.getMinimumWidth()两者中的最大值。

mBackground.getMinimumWidth()的代码如下:

/**     * Returns the minimum width suggested by this Drawable. If a View uses this     * Drawable as a background, it is suggested that the View use at least this     * value for its width. (There will be some scenarios where this will not be     * possible.) This value should INCLUDE any padding.     *     * @return The minimum width suggested by this Drawable. If this Drawable     *         doesn't have a suggested minimum width, 0 is returned.     */    public int getMinimumWidth() {        final int intrinsicWidth = getIntrinsicWidth();        return intrinsicWidth > 0 ? intrinsicWidth : 0;    }

它返回的是Drawable的原始宽度,如果Drawable有原始宽度的话。否则返回0.

 

因此若view有设置背景,那么size就是android:minWidth和背景最小宽度这两者的最大值,若没有设置背景,那么size的值就是android:minWidth的值。

转载于:https://www.cnblogs.com/tangZH/p/7029372.html

你可能感兴趣的文章
jQuery-DOM操作之html()、text()、val()
查看>>
阅读《Effective C++》系列
查看>>
(转)Android技术积累:图片缓存管理
查看>>
MyEclipse6.5安装SVN插件的三种方法
查看>>
Oracle游标声明
查看>>
Mysql相关技术细节整理
查看>>
20160427Struts2--入门1
查看>>
如何搭建javaweb 开发环境
查看>>
输入年月日,看看格式是否正确。
查看>>
hotplug/mdev机制
查看>>
Deepin深度Linux系统安装记录
查看>>
.net OADate 转javascript的Datetime
查看>>
nova-network
查看>>
LAMP企业架构读写分离
查看>>
CodeForces 69D Dot :两个人轮流移动棋子,移动方法有n种,谁先移动到距离原点>d则输,问谁赢 :博弈+记忆化...
查看>>
PHP高效率写法
查看>>
设计师如何提高产品思维 | 设计思考
查看>>
HP大中华区总裁孙振耀退休感言(转)
查看>>
嵌套在母版页中的repeater自动生成控件ID
查看>>
数据访问层工具类
查看>>