自定义View(8)关于measure->onMeasur->setMeasuredDimension及getDefaultSize,resolveSizeAndState
参考: http://www.cnblogs.com/xiaorenwu702/p/5185436.html
当外层容器组件调用其内部的某个组件view1.measure(xxx)时,view1的onMeasure(xxx)就被调用。
1,measure--->onMeasure--->setMeasuredDimension 流程
Android通过调用View的measure()方法对View进行量算,让该View的父控件知道该View想要多大的尺寸空间。
- 在View的measure方法会首先从成员变量中读取以前缓存过的量算结果,如果能找到该缓存值,那么就基本完事了。
- 如果没有找到缓存值,那么measure方法会执行onMeasure回调方法,measure方法会将上述的宽度和高度的限制条件依次传递给onMeasure方法。
- onMeasure方法会完成具体的量算工作,并将量算的结果通过调用View的setMeasuredDimension方法保存到View的成员变量mMeasuredWidth 和mMeasuredHeight中。
2,measure 的工作
判断1:
View先查看是不是要强制量算以及这次measure中传入的MeasureSpec与上次量算的MeasureSpec是否相同,如果不是强制量算或者MeasureSpec与上次的量算的MeasureSpec相同,那么View就不必真的去量算了。
判断2:
如果不满足上述条件,View就考虑去做量算工作。但是在量算之前,View还想偷懒,它会以MeasureSpec计算出的key值作为键,去成员变量mMeasureCache中查找是否缓存过对应key的量算结果,如果能找到,那么就简单调用一下setMeasuredDimensionRaw方法,将从缓存中读到的量算结果保存到成员变量mMeasuredWidth和mMeasuredHeight中。
最后:
如果不能从mMeasureCache中读到缓存过的量算结果,那么这次View就真的不能再偷懒了,只能乖乖地调用onMeasure方法去完成实际的量算工作,并且将尺寸限制条件widthMeasureSpec和heightMeasureSpec传递给onMeasure方法。关于onMeasure方法,我们会在下面详细介绍。
2,onMeasure的工作
a.估算宽,高最小值,不要忘记计算leftpadding,rightpadding等。
b.解析它传来的参数,得到最终值,如果是重写的ViewGroup,要调用其中的子view的measure方法。
c.把测量到的数据保存到mMeasuredWidth和mMeasuredHeight中。
示范:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // Try for a width based on our minimum
//最小宽度
int w = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth(); //如果给出的建议是0,可以手动设置一个期望值。单位是像素。同时这步一定要在resolveSizeAndState前,
// 因为它可能大于widthMeasureSpec的最大值。
if (w == ) w = ; //计算最佳值,在其中解析了 widthMeasureSpec
w = resolveSizeAndState(w, widthMeasureSpec, ); // Whatever the width ends up being, ask for a height that would let the pie
// get as big as it can
//最小高度
int h = getSuggestedMinimumHeight() + getPaddingBottom() + getPaddingTop(); //如果给出的建议是0,可以手动设置一个期望值。单位是像素。同时这步一定要在resolveSizeAndState前,
// 因为它可能大于heightMeasureSpec的最大值。
if (h == ) h = ; //计算最佳值,在其中解析了 heightMeasureSpec
h = resolveSizeAndState(h, heightMeasureSpec, ); //将量算的结果保存到View的成员变量mMeasuredWidth 和mMeasuredHeight中。
setMeasuredDimension(w, h); // 量算完成之后,View的父控件就可以通过调用
// getMeasuredWidth、getMeasuredState、getMeasuredWidthAndState
// 这三个方法获取View的量算结果。 }
3,setMeasuredDimension的工作
将量算的结果通过调用View的setMeasuredDimension方法保存到View的成员变量mMeasuredWidth 和mMeasuredHeight中。
注意这两个变量,它们的含义并不是一个纯值。
以mMeasuredWidth为例,它是一个Int类型的值,这4个字节中有两个含义:
- 其高位的第一个字节为第一部分,用于标记量算完的尺寸是不是达到了View想要的宽度,我们称该信息为量算的state信息。
- 其低位的三个字节为第二部分,用于存储实际的量算到的宽度。
getMeasuredWidth系列方法返回的就是纯宽度值,不包含state信息,把mMeasuredWidth的第一部分去掉。
public final int getMeasuredWidth() {
//MEASURED_SIZE_MASK的值为0x00ffffff,用mMeasuredWidth与掩码MEASURED_SIZE_MASK进行按位与运算,
//可以将返回值中的高位字节的8个bit位全置为0,从而去掉了高位字节的state信息
return mMeasuredWidth & MEASURED_SIZE_MASK;
}
4,resolveSizeAndState和getDefaultSize的区别
前者返回的数据中包含state信息,后者只是纯大小。
5,什么是MeasureSpec
MeasureSpec作用:
A MeasureSpec encapsulates the layout requirements passed from parent to child. Each MeasureSpec represents a requirement for either the width or the height. A MeasureSpec is comprised of a size and a mode. There are three possible modes:
一个MeasureSpec压缩了父组件递给子组件的宽高信息,这个值最终被压缩到一个int内(如onMeasure(int widthMeasureSpec,int heightMeasureSpec)中的两个参数),也可以用MeasureSpec解析这个int得到真正的宽,高。一个MeasureSpec由大小和模式组成。
MeasureSpec三种模式:
UNSPECIFIED:
This is used by a parent to determine the desired dimension of a child View. For example, aLinearLayout may call measure() on its child with the height set to UNSPECIFIED and a width ofEXACTLY 240 to find out how tall the child View wants to be given a width of 240 pixels.
这种情况,是由外层容器父组件决定其子组件的大小,重写onMeasure时,这种模式不用测量。交给外层容器处理。
如:父组件可以把模式为UNSPECIFED,大小为不知的高度描述信息和一个EXACTLY模式,大小为240px的宽度描述信息传给子组件的onMeasure,这时子组件不用测量这个高,它由父根据子组件的宽度计算一个合适的高度。
This is used by the parent to impose an exact size on the child. The child must use this size, and guarantee that all of its descendants will fit within this size.
这种模式是父组件强制要求子组件的一个值,子组件重写onMeasure时必需用它。且要保证子组件的后代都要在这个值之内。
This is used by the parent to impose a maximum size on the child. The child must guarantee that it and all of its descendants will fit within this size.
这种模式是父组件强制要求子组件的一个最大值,子组件要保证其与后代都要在这个值之内。
MeasureSpec常用的4个函数:
| Public Methods | ||
| static int getMode(int measureSpec) | Extracts the mode from the supplied measure specification. | 提取模式(上述三个模式之一) |
| static int getSize(int measureSpec) | Extracts the size from the supplied measure specification. | 提取大小值 |
| static int makeMeasureSpec(int size, int mode) | Creates a measure specification based on the supplied size and mode. | 把大小和模式压缩到一个int中 |
| static String toString(int measureSpec) | Returns a String representation of the specified measure specification. | 返回字符串 |
自定义View(8)关于measure->onMeasur->setMeasuredDimension及getDefaultSize,resolveSizeAndState的更多相关文章
- Android自定义View前传-View的三大流程-Measure
Android自定义View前传-View的三大流程-Measure 参考 <Android开发艺术探索> https://developer.android.google.cn/refe ...
- 自定义View Measure过程(2)
目录 目录 1. 作用 测量View的宽/高 在某些情况下,需要多次测量(measure)才能确定View最终的宽/高: 在这种情况下measure过程后得到的宽/高可能是不准确的: 建议在layou ...
- android 自定义View onMeasure中 super.onMeasure 和 setMeasuredDimension
练习写一个自定义的view,代码是抄网上的,第一次写,没有问题,与网上的示例一样的效果, 第二次.第三次,都出现问题,但是解决了. 昨天进行第四次写再写,又出问题不一样的问题了. 首先是想加一个子包, ...
- 【Android - 自定义View】之View的measure过程解析
measure(测量)过程是View的工作流程中最开始.最核心的过程,在这个过程中负责确定View的测量宽/高. 对于View和ViewGroup,measure过程有不同的执行方法:如果目标是一个原 ...
- Android 自定义View及其在布局文件中的使用示例
前言: 尽管Android已经为我们提供了一套丰富的控件,如:Button,ImageView,TextView,EditText等众多控件,但是,有时候在项目开发过程中,还是需要开发者自定义一些需要 ...
- Android之自定义View的实现
对于学习Android开发的小童鞋对于自定义View一定不会陌生,相信大家对它是又爱又恨,爱它可以跟随我们的心意设计出漂亮的效果:恨它想要完全流畅掌握,需要一定的功夫.对于初学者来说确实很不容易,网上 ...
- Android 自定义View及其在布局文件中的使用示例(三):结合Android 4.4.2_r1源码分析onMeasure过程
转载请注明出处 http://www.cnblogs.com/crashmaker/p/3549365.html From crash_coder linguowu linguowu0622@gami ...
- Android中View的绘制过程 onMeasure方法简述 附有自定义View例子
Android中View的绘制过程 onMeasure方法简述 附有自定义View例子 Android中View的绘制过程 当Activity获得焦点时,它将被要求绘制自己的布局,Android fr ...
- 自定义View和ViewGroup
为了扫除学习中的盲点,尽可能多的覆盖Android知识的边边角角,决定对自定义View做一个稍微全面一点的使用方法总结,在内容上面并没有什么独特的地方,其他大神们的博客上面基本上都有讲这方面的内容,如 ...
- 转 自定义View之onMeasure()
可以说重载onMeasure(),onLayout(),onDraw()三个函数构建了自定义View的外观形象.再加上onTouchEvent()等重载视图的行为,可以构建任何我们需要的可感知到的自定 ...
随机推荐
- BZOJ 5028 小Z的加油店
[题解] 本题要求求出区间内的各个元素通过加减之后能够得出的最小的数,那么根据裴蜀定理可知答案就是区间内各个元素的最大公约数. 那么本题题意化简成了维护一个序列,支持区间加上某个数以及查询区间元素的最 ...
- 【Codeforces 486C】Palindrome Transformation
[链接] 我是链接,点我呀:) [题意] 光标一开始在p的位置 你可以用上下左右四个键位移动光标(左右)或者更改光标所在的字符(上下增加或减少ascill码) 问你最少要操作多少次才能使得字符串变成回 ...
- @Value取值为NULL的解决方案------https://blog.csdn.net/zzmlake/article/details/54946346
@Value取值为NULL的解决方案 https://blog.csdn.net/zzmlake/article/details/54946346
- BNUOJ 33895 D-City
D-City Time Limit: 1000ms Memory Limit: 65535KB This problem will be judged on HDU. Original ID: 449 ...
- Python学习笔记 (2.2)Python中的字符编码问题及标准数据类型之String(字符串)
Python3中的String类型 首先,Python中没有字符类型,只有字符串类型.单个字符按照长度为1的字符串处理,这对于曾是OIER的我来说有点不适应啊. 字符串的表示方法 最常用的就是用一对双 ...
- hdu2852 KiKi's K-Number
题意:给定三个操作添加删除查询大于a的的第k大值----树状数组的逆向操作 给定a利用BIT查询有多少值比a小,这样比a大的k大值就应该有k+sum(a)个小于他的值 因此可以二分枚举k大值看看是不是 ...
- spring-boot | 整合通用Mabatis 分页插件PageHelper
Mybatis通用Mapper介绍 Mybatis 通用 Mapper 极其方便的使用 Mybatis 单表的增删改查,支持单表操作,不支持通用的多表联合查询 优点: 通用 Mapper 可以极大的方 ...
- HDU 4499 Cannon (暴力搜索)
题意:在n*m的方格里有t个棋子,问最多能放多少个炮且每一个炮不能互相攻击(炮吃炮) 炮吃炮:在同一行或同一列且中间有一颗棋子. #include <stdio.h> #include & ...
- iOS截取视频某一帧图片(关键帧,AVAssetImageGenerator)
获取第一帧图片 导入 AVFoundation.Framework.CoreMedia.Framework 实现代码例如以下: + (UIImage*) thumbnailImageForVideo: ...
- Android实现一个自己定义相机的界面
我们先实现拍照button的圆形效果哈.Android开发中,当然能够找美工人员设计图片,然后直接拿进来.只是我们能够自己写代码实现这个效果哈.最经常使用的的是用layout-list实现图片的叠加, ...