Android View工作机制(2)—measure过程 上
来源:互联网 发布:炫酷证书单页源码 编辑:程序博客网 时间:2024/06/05 03:35
为了理解View的测量过程,我们先要了解MeasureSpec。从字面意思看MeasureSpec是测量规格的意思。在Android中,MeasureSpec是一个32位的int值,高2位代表specMode,即测量模式,后30位代表品SpecSize,为某种测量模式下的规格大小。SpecMode有三种,分别为:1. UNSPECIFIED 父容器对View没有限制,View想多大就多大2. EXACTLY 父容器已经检测出View所需要的精确大小,此时View的大小就是SpaceSize。它对应于LayoutParams中的match_parent。3. AT_MOST父容器指定了一个大小,即SpaceSize,View的大小不能大于这个值。它对应了LayoutParams中的wrap_content。由此规则,我们可以对View的MeasureSpace的创建规则进行一个归纳。(参考自《Android开发艺术探索》)
View的measure过程是一个final方法,所以子类不能重写这个方法。View的方法会调用View的onMeasure方法。onMeasure方法的源码如下
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); }
在onMeasure方法中,通过setMeasureDimension方法设置View的宽高。下面我们来看一下getDefaultSize方法的实现。
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; }
可以发现,在这个方法中获取了SpaceSize和SpaceMode,根据SpaceMode的不同进行不同的设置。如果是UNSPECIFIED模式,则结果的大小就参数中的size,否则是获取到的SpaceSize。而getDefaultSize方法中的宽高获取的方法为getSuggestedMinimumWidth,此方法的实现为
protected int getSuggestedMinimumWidth() { return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth()); }
从此段代码可以看出,如果View没有设置背景,那么他的宽度为mMinWidth,否则为mMinWidth和背景大小中比较大的那一个。那么背景的Drawable.getMinImunWidth方法获取的是什么呢?查看此方法的源码
public int getMinimumHeight() { final int intrinsicHeight = getIntrinsicHeight(); return intrinsicHeight > 0 ? intrinsicHeight : 0; }
这段代码的含义是,获取这个背景Drawable的初始高度,如果高度大于0,则返回背景的高度,否则返回0。从getDefaultSize的实现来看,View的宽高是由SpaceSize决定的。为了使用View的wrap_content属性,我们在自定义View的时候,需要重写View的onMeasure方法。编写的方法可以模仿系统自己内部测量的getDefaultSize方法。下面我们来举个例子:新建一个类,为MyView.java,继承自View实现View的onMeasure方法代码如下:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); }
编写方法measureWidth和measureHeight,测量View的宽高,这里我们假定View最大为200px。则measureWidth方法的实现如下:
private int measureWidth(int measureSpace) { int result = 0; int spaceMode = MeasureSpec.getMode(measureSpace); //获取测量模式 int spaceSize = MeasureSpec.getSize(measureSpace); //获取测量的大小 if (spaceMode == MeasureSpec.EXACTLY) { result = spaceSize; } else { result = 200; //最大为200 if (spaceMode == MeasureSpec.AT_MOST) { //如果是AT_MOST模式,则将宽度设置为200和spaceSize中比较小的那个 result = Math.min(result, spaceSize); } } return result; }
measureHeight的实现类似于measureWidth方法。我们着重讲解下AT_MOST模式下的那部分代码。如果检测到AT_MOST模式,那么我们先假定宽为最大值200。再将200与spaceSize比较。获取最小的那个。这样,我们在指定了wrap_content的时候,View的大小就为200。如果我们指定了比200还大的宽度,那么View仍然会把高度限制在200px,如果小于200,那么执行的是EXACTLY模式下的了逻辑,宽度就为我们设置的宽度,即spaceSize。我们在布局文件中放置自定义的View
<MyView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/holo_red_dark" />
运行效果如下所示
此时可以看出,我们将宽高设置为wrap_content的时候,View的大小均为200px。设置为其他大小的情况读者可以自行实验。
0 0
- Android View工作机制(2)—measure过程 上
- Andorid View工作机制(3)—measure过程 下
- Android View measure过程
- android-View工作原理(三)视图大小计算过程(measure过程)
- View的工作流程---Measure过程
- View的工作原理之measure过程
- Android View的工作流程总结分析(二)-Measure
- Android View框架的measure机制
- Android View框架的measure机制
- Android View框架的measure机制
- (转)Android View框架的measure机制
- Android View框架的measure机制
- Android View框架的measure机制
- Android View框架的measure机制
- 【Android】View绘制过程分析之measure
- android View measure过程源码解析
- 浅析Android View的Measure过程
- Android应用程序窗口View的measure过程
- webstorm 设置uglify 压缩js文件
- C++作业7
- 梳理mybatis-使用篇
- 移动端用户体验:获取用户权限的正确方式
- Android手机平板两不误,使用Fragment实现兼容手机和平板的程序
- Android View工作机制(2)—measure过程 上
- UIResponder介绍
- 短信备份与还原&AsyncTask&程序锁(Fragment)
- SICP 习题2.10 区间除法 被除区间横跨0的问题
- Java基础-包讲解
- 你的数据安全吗
- 大事记
- 【总结】排序算法汇总
- 一些加密方式(更新中)