现在的位置: 首页 > 综合 > 正文

Android学习札记3:对View.MeaureSpec的一些理解

2018年04月04日 ⁄ 综合 ⁄ 共 1812字 ⁄ 字号 评论关闭


MeasureSpec封装了从父控件传给子控件的布局要求。每个MeasureSpec都描述了包括宽度和高度的要求。
MeasureSpec由大小(size)和模式(mode)组成,这里有三种可能的模式(mode):
    UNSPECIFIED(未指定):
        父控件没有对子控件进行任何的限制,子控件可以是任意大小。
    EXACTLY(指定):
       父控件已经指定了具体的尺寸大小给子控件,子控件必须按照指定的大小界限显示而不能随意地改变。
    AT_MOST(尽可能大):
        子控件可以在指定尺寸大小的范围内尽可能大地显示。
    为了减少对象分配,MeasureSpec必须整形实现。


一般来说,自定义控件都会去重写View的onMeasure方法,因为该方法指定控件在屏幕上的显示大小。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
onMeasure方法的两个参数是由其上一层父控件传入的,有多种情况,重写该方法时需要计算控件的实际大小,然后调用setMeasureDiemension(int, int)来设置。
onMeasure方法的两个参数widthMeasureSpec和heightMeasureSpec不是一般的尺寸数值,而是将大小和模式组合在一起的数值。需要通过
int size = MeasureSpec.getSize(widthMeasureSpec)得到大小,通过int mode = MeasureSpec.getMode(widthMeasureSpec)得到模式。

mode共有三种情况,取值分别为MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY,MeasureSpec.AT_MOST。
MeasureSpec.UNSPECIFIED是未指明尺寸大小,这种情况不多,一般情况下是当父控件是AdapterView时通过measure方法传入的模式。
MeasureSpec.EXACTLY是精确尺寸,将控件的layout_width或layout_height指定为具体数值时或者fill_parent时,是控件大小已经确定的情况,都是精确尺寸。
MeasureSpec.AT_MOST是最大尺寸,将控件的layout_width或layout_height指定为wrap_content时,控件大小一般随着该控件的子控件或内容的变化而变化,此时
该控件尺寸只要不超过父控件允许的最大尺寸即可。因此,mode是AT_MOST时,size为父控件允许的最大尺寸。

因此,在重写onMeasure方法时要根据模式不同进行大小计算。下面的代码就是一种比较典型的方法:

@Override    
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    
    setMeasuredDimension(getMeasuredLength(widthMeasureSpec, true), getMeasuredLength(heightMeasureSpec, false));    
}    
    
    
private int getMeasuredLength(int length, boolean isWidth) {    
    int specMode = MeasureSpec.getMode(length);    
    int specSize = MeasureSpec.getSize(length);    
    int size;    
    int padding = isWidth ? getPaddingLeft() + getPaddingRight()    
            : getPaddingTop() + getPaddingBottom();    
    if (specMode == MeasureSpec.EXACTLY) {    
        size = specSize;    
    } else {    
        size = isWidth ? padding + mWave.length / 4 : DEFAULT_HEIGHT    
                + padding;    
        if (specMode == MeasureSpec.AT_MOST) {    
            size = Math.min(size, specSize);    
        }    
    }    
    return size;    
} 

参考资料:http://www.blogjava.net/liuyanbo/archive/2012/03/15/371969.html

抱歉!评论已关闭.