自定义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()等重载视图的行为,可以构建任何我们需要的可感知到的自定 ...
随机推荐
- codechef营养题 第二弹
第二弾が始まる! codechef problems 第二弹 一.Backup Functions 题面 One unavoidable problem with running a restaura ...
- noip模拟赛 列车调度
[ 问题描述 ] 有N辆列车,标记为1,2,3,…,N.它们按照一定的次序进站,站台共有K个轨道,轨道遵从 先进先出的原则.列车进入站台内的轨道后可以等待任意时间后出站,且所有列车不可后退.现在要使出 ...
- VScode输出中文乱码的解决方法------测试过可以用
用python写个爬虫,配置个VScode环境,发现输出都是乱码,翻阅网站后发现一个简单有效的方法,在此谢过网络上的大牛们的无私分享,我也在此记录一下,以备后用: 文件---->首选项----& ...
- 【BZOJ4199&UOJ131】品酒大会(后缀数组,并查集)
题意: 两杯“r相似” (r>1)的酒同时也是“1 相似”.“2 相似”.…….“(r−1) 相似”的. n<=300000 abs(a[i])<=10^9 思路:对于i,j两个后缀 ...
- codevs1031 质数环
一个大小为N(N<=17)的质数环是由1到N共N个自然数组成的一个数环,数环上每两个相邻的数字之和为质数.如下图是一个大小为6的质数环.为了方便描述,规定数环上的第一个数字总是1.如下图可用1 ...
- JVM即时编译(JIT)
Java解释执行过程: 代码装入-代码校验-代码执行 Java字节码的执行方式分为两种:即使编译方式和解释执行方式.即时编译是值解释器先将字节码编译成机器码,然后执行该机器码.解释执行的方式是指解释器 ...
- 一个性能较好的jvm參数配置以及jvm的简单介绍
一个性能较好的webserverjvm參数配置: -server //服务器模式 -Xmx2g //JVM最大同意分配的堆内存,按需分配 -Xms2g //JVM初始分配的堆内存.一般和Xmx配置成一 ...
- Android Message和obtainMessage的差别
前几天须要实现一个以太网功能就看了以太网的源代码部分,看见了源代码部分在消息处理时,发现有一些不同的地方: 平时我在处理消息时: 1.首先创建Handler对象: private Hand ...
- C++中switch 语句中的变量声明和
switch 内部的变量定义: ; switch(i) { : string str; //error ; //error int val2; //right ; //right : val2 = ; ...
- ROADS - Roads
N cities named with numbers 1 ... N are connected with one-way roads. Each road has two parameters a ...