android的布局分两个阶段,先measure()后requestLayout(),一个MeasureSpec封装了父布局传给子布局的布局要求。每个MeasureSpec代表了一个宽度或高度的要求。一个MeasureSpec包含一个尺寸和模式.
有三种可能的模式:
UNSPECIFIED:父布局没有给子布局任何限制,子布局可以任意大小。
EXACTLY: 父布局决定子布局的确切大小。不论子布局多大,它都必须限制在这个界限里。
AT_MOST: 子布局可以根据自己的大小选择任意大小。
它常用的三个函数:
1.static int getMode(int measureSpec):按照供给的测量值(格局)提取模式(上述三个模式之一)
2.static int getSize(int measureSpec):按照供给的测量值(格局)提取大小值(这个大小也就是我们凡是所说的大小)
3.static int makeMeasureSpec(int size,int mode):按照供给的大小值和模式创建一个测量值(格局)
为了减少内存分配,MeasueSpecs用整数表示。这个类提供打包和解包元组为整型。
参考方法:public static int makeMeasureSpec(int size,int mode)。
onMeasure方法在控件的父元素将要放置它的子控件时调用。它会问一个问题,“你想要用多大地方啊?”,然后传入两个参数——widthMeasureSpec和heightMeasureSpec。它们指明控件可获得的空间以及关于这个空间描述的元数据。比返回一个结果要好的方法是你传递View的高度和宽度到setMeasuredDimension方法里。
接下来的代码片段给出了如何重写onMeasure。注意,调用的本地空方法是来计算高度和宽度的。它们会译解widthHeightSpec和heightMeasureSpec值,并计算出合适的高度和宽度值。
Java代码:
- @Override
- protected void onMeasure(intwidthMeasureSpec,intheightMeasureSpec){
- int measuredHeight=measureHeight(heightMeasureSpec);
- int measuredWidth=measureWidth(widthMeasureSpec);
- setMeasuredDimension(measuredHeight,measuredWidth);
- }
-
- private int measureHeight(intmeasureSpec){
- //高度测量窗口的回归.
- }
-
- private int measureWidth(intmeasureSpec){
- //还测量窗口的宽度.
- }
边界参数——widthMeasureSpec和heightMeasureSpec以整数的方式传入(出于对效率的考虑)。在它们使用之前,首先要做的是使用MeasureSpec类的静态方法getMode和getSize来译解,如下面的片段代码所示:
Java代码:
- int specMode=MeasureSpec.getMode(measureSpec);
- int specSize=MeasureSpec.getSize(measureSpec);
接下来的框架代码给出了处理View测量的典型实现:
Java代码:
- @Override
- protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec){
- int measuredHeight=measureHeight(heightMeasureSpec);
- int measuredWidth=measureWidth(widthMeasureSpec);
- setMeasuredDimension(measuredHeight,measuredWidth);
- }
-
- private int measureHeight(int measureSpec){
- int specMode=MeasureSpec.getMode(measureSpec);
- int specSize=MeasureSpec.getSize(measureSpec);
-
- //如果没有限制默认大小是指定的.
- int result=500;
- if(specMode==MeasureSpec.AT_MOST)
- {
- //你理想的大小的计算
- //在这个最大值控制.
- //如果你能控制的充满可用
- //外太空返回束缚.
- result=specSize;
- }
- else if(specMode==MeasureSpec.EXACTLY)
- {
- //如果你的控制能符合这些界限返回那个价值.
- result=specSize;
- }
- return result;
- }
-
- private int measureWidth(int measureSpec){
- int specMode=MeasureSpec.getMode(measureSpec);
- int specSize=MeasureSpec.getSize(measureSpec);
-
- //如果没有限制默认大小是指定的.
- int result=500;
- if(specMode==MeasureSpec.AT_MOST)
- {
- //理想尺寸的计算你的控制
- //在这个最大的尺寸。
- //如果你的控制填充的可用空间
- //返回外面的束缚。
- result=specSize;
- }
- else if(specMode==MeasureSpec.EXACTLY)
- {
- //如果你的控制能符合这些界限返回那个价值.
- result=specSize;
- }
- return result;
- }
Creation
Constructors
onFinishInflate() 当View和它的所有子对象从XML中导入之后,调用此方法
Layout
onMeasure(int, int) View会调用此方法,来确认自己及所有子对象的大小
onLayout(boolean, int, int, int, int, int, int) 当View要为所有子对象分配大小和位置时,调用此方法
onSizeChanged(int, int, int, int) 当View大小改变时,调用此方法
Drawing
onDraw(Canvas) 当View要绘制它的内容时,调用此方法
Event processing
onKeyDown(int, KeyEvent) 当一个新的按键事件发生时,调用此方法
onKeyUp(int, KeyEvent) 当一个按键释放事件发生时,调用此方法
onMotionEvent(MotionEvent) 当一个动作事件(如触摸)发生时,调用此方法
Focus
onFocusChanged(boolean, int) 当View获得或失去焦点时,调用此方法
Attaching
onAttachedToWindow() 当View附加到一个窗体上时,调用此方法
onDetachedFromWindow() 当View离开它的窗体时,调用此方法
当你为一个 activty 添加一个可见的 view, 并且运行这个activty时,android通常情况下会自动按照下列顺序来触发view的相关
事件
onAttachedToWindow
onMeasure
onSizeChanged
onLayout
onDraw
来源: