自定义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()等重载视图的行为,可以构建任何我们需要的可感知到的自定 ...
随机推荐
- #if 0的意义和好处
在调试中经常遇到,写好的程序,需要调试相反的两方面,如:有两款单片机的程序,分别对应着不同的硬件引脚,我们把代码都写上了,但是不能同时让他们起效,通常的办法是/**/屏蔽一些段落,但是调试起来很麻烦. ...
- 《阿里巴巴Java开发手册》更新为《Java开发手册》
新版一览:华山版<Java开发手册> <阿里巴巴Java开发手册>始于阿里内部规约,在全球Java开发者共同努力下,已成为业界普遍遵循的开发规范,涵盖编程规约.异常日志.单元测 ...
- 【OpenCV, MFC, DIP】向图像中加入各种噪声
1.椒盐噪声 Mat dstImage = srcImage.clone(); ; k < n; k++) { //随机取值行列 int i = rand() % dstImage.rows; ...
- EF中避免查询重复执行的手段
由于ef有lazyload机制,编写的查询语句往往都没有立即执行,当你轮训结果集的时候才会将查询翻译成database端的sql语句,执行sql将结果返回到方法中.但是,下次再使用前面的结果集的时候, ...
- Java基础学习总结(87)——坚持写Java等技术类博客的好处
1.加深对技术点的理解 每天写博客,可以加深对技术点的理解,假如工作中,对某个技术点运用的不熟,当你通过博客的形式写出来,这个过程中,遇到不懂的知识点,你就会查阅相关的资料,弄明白他. 2.自己日后用 ...
- noip模拟赛 都市
分析:是一道非常有意思的题,30分的暴力的话枚举每个位置是什么数,然后排个序,用map判一下重就好了,比较麻烦. 满分做法显然不可能讨论每个位置所有的情况,肯定是有规律的,现将这n*(n-1)/2个数 ...
- HDU——1134 Game of Connections
Game of Connections Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Othe ...
- what happens if we dont resolve or reject the promise
https://stackoverflow.com/questions/36734900/what-happens-if-we-dont-resolve-or-reject-the-promise I ...
- 1. CountDiv 数数有几个 Compute number of integers divisible by k in range [a..b].
package com.code; public class Test05_1 { public static int solution(int A, int B, int K) { // handl ...
- 如何修改ICO文件的尺寸
使用Axialis IconWorkshop,该软件下载地址: http://www.xiazaiba.com/html/161.html 尺寸过大的ICO将无法作为应用程序的图标,如下图所示,这些素 ...