Android View-measure
来源:互联网 发布:linux 进入mysql 编辑:程序博客网 时间:2024/04/30 15:19
View#measure(int widthMeasureSpec, int heightMeasureSpec),Android布局机制的第一阶段,这阶段是为了了解一个View应该有多大。父节点在参数中提供约束信息。参数:
- widthMeasureSpec:父节点对子View宽度的约束
- heightMeasureSpec:父节点对子View高度的约束
View的实际度量工作是按此方法调用的onMeasure(int,int)进行的。因此,只有onMeasure(int,int)才能而且必须被子类覆盖。源码:
public final void measure(int widthMeasureSpec, int heightMeasureSpec) { //视觉边界模式时对widthMeasureSpec和heightMeasureSpec进行调整 boolean optical = isLayoutModeOptical(this); if (optical != isLayoutModeOptical(mParent)) { Insets insets = getOpticalInsets(); int oWidth = insets.left + insets.right; int oHeight = insets.top + insets.bottom; widthMeasureSpec = MeasureSpec.adjust(widthMeasureSpec, optical ? -oWidth : oWidth); heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight); } // 将父布局的约束条件widthMeasureSpec和heightMeasureSpec组成一个long,作为key用于缓存 long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL; if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2); //如果需要强制布局 或 新旧widthMeasureSpec、heightMeasureSpec不同 if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT || widthMeasureSpec != mOldWidthMeasureSpec || heightMeasureSpec != mOldHeightMeasureSpec) { //清除 设置了测量尺寸标记 mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET; //解析所有与RTL相关的属性 resolveRtlPropertiesIfNeeded(); //如果是强制布局cacheIndex == -1,mMeasureCache.indexOfKey(key)没有缓存返回负数 int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 : mMeasureCache.indexOfKey(key); if (cacheIndex < 0 || sIgnoreMeasureCache) {//不使用缓存 onMeasure(widthMeasureSpec, heightMeasureSpec);//实际度量工作在onMeasure(int,int)里 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;//清除 layout前需要测量标记 } else {//使用缓存 //获取缓存的 父布局的约束条件widthMeasureSpec和heightMeasureSpec组成的key的值 long value = mMeasureCache.valueAt(cacheIndex); //设置测量尺寸,里面添加了 设置了测量尺寸标记 setMeasuredDimensionRaw((int) (value >> 32), (int) value); mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;//添加 layout前需要测量标记 } //没有调用setMeasuredDimension(int,int)会抛出异常 if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) { throw new IllegalStateException("View with id " + getId() + ": " + getClass().getName() + "#onMeasure() did not set the" + " measured dimension by calling" + " setMeasuredDimension()"); } //添加 需要layout标记 mPrivateFlags |= PFLAG_LAYOUT_REQUIRED; } //记录新的widthMeasureSpec和heightMeasureSpec mOldWidthMeasureSpec = widthMeasureSpec; mOldHeightMeasureSpec = heightMeasureSpec; //将 父布局的约束条件组成的key 和 新的widthMeasureSpec和heightMeasureSpec缓存起来 mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 | (long) mMeasuredHeight & 0xffffffffL); }
方法添加了final修饰,子类有需要时应该重写onMeasure(int ,int)以完成自己的测量方式。
不了解视觉边界模式的可以看看这篇文章,Android 4.3中的视觉边界布局(Optical bounds layout)。
关于onMeasure(int ,int)欢迎看看我写的Android自定义View-onMeasure介绍 - oJin的博客 - CSDN博客
关于方法里面用到的标记:
PFLAG_FORCE_LAYOUT:在调用了requestLayout()或forceLayout()时会添加上该标记。
PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT:在measure(int,int)方法中使用缓存来设置测量尺寸时添加该标记。
PFLAG_LAYOUT_REQUIRED:在measure(int,int)方法中进行测量后添加该标记。
PFLAG_MEASURED_DIMENSION_SET:在measure(int,int)方法中进行测量前清除标记,如果测量后没有添加该标记会抛出异常。在setMeasuredDimensionRaw(int, int)中添加标记,setMeasuredDimension(int, int)中会调用setMeasuredDimensionRaw(int, int)方法。
- 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 (二) 自定义UI控件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 (一) 流程分析
- javaWeb开发过程中遇到的乱码问题
- 方法重写的一大两小两同
- 高偏差、高方差、低精确率与低召回率、混淆矩阵
- Java实现二分查找
- js实现页面弹框效果
- Android View-measure
- caffe训练模型并预测图片类型
- NYOJ 40
- Python读取中文路径时的处理
- NOIP2016 愤怒的小鸟 [状压DP]
- CSDN-Markdown使用方法
- hdu 5673 线性求逆元+卡特兰数
- 谈谈个人网站的建立(四)—— 日志系统的建立
- 生产者消费者模式解决强耦合问题