onMeasure学习笔记

在学习自定义view时,对onMeasure的理解真是很困难,网上的资料说的都大从官网上摘下来的,而且说得不明不白,看起来就犯晕。
没办法,只好自己通过实例来仔细研究一下。但研究之前,必须先对这个onMeausre的方法有个大致的理解。

onMeasure(int widthMeasureSpec, int heightMeasureSpec)Called to determine the size requirements for this view and all of its children.

Parameters
widthMeasureSpec horizontal space requirements as imposed by the parent. The requirements are encoded with View.MeasureSpec.
heightMeasureSpec vertical space requirements as imposed by the parent. The requirements are encoded with View.MeasureSpec.
从上面的解释,我们知道:

  1. onMeasure的两个参数用于测量水平和垂直空间大小,具体怎么测量,不得而知
  2. onMeasure被调用时用来决定当前view以及所有它的子view的尺寸请求
我一直搞不清楚两个参数的实际作用,所以只能通过实例来测试一下:

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	        System.out.println(widthMeasureSpec+":"+heightMeasureSpec);
		int w = getMeasureWidth(widthMeasureSpec);  
		int h = getMeasureHeight(heightMeasureSpec);

		setMeasuredDimension(w, h);  \\必须调用此方法,否则会抛出异常
	}

	private int getMeasureHeight(int heightMeasureSpec) {
		int result = 0;
		int size = MeasureSpec.getSize(heightMeasureSpec);  \\每次调用此方法,测量用到的size会发生变化
		int mode = MeasureSpec.getMode(heightMeasureSpec);  \\根据定义的Layout_width,Layout_height,会对此值产生影响
		if (mode == MeasureSpec.EXACTLY) {
			result = size;
		} else if (mode == MeasureSpec.UNSPECIFIED) {
			result = (int) paint.measureText("") + getPaddingLeft()
					+ getPaddingRight();
		} else {
			result = Math.min(result, size);
		}
		System.out.println("Height size:" + size);  
		System.out.println("Height mode:" + mode);
		return result;
	}

	private int getMeasureWidth(int widthMeasureSpec) {
		int result = 0;
		int size = MeasureSpec.getSize(widthMeasureSpec);
		int mode = MeasureSpec.getMode(widthMeasureSpec);
		if (mode == MeasureSpec.EXACTLY) {
			result = size;
		} else if (mode == MeasureSpec.UNSPECIFIED) {
			result = (int) paint.measureText("") + getPaddingTop()
					+ getPaddingBottom();
		} else {
			result = Math.min(result, size);
		}
		System.out.println("Width size:" + size);
		System.out.println("Width mode:" + mode);
		return result;
	}
请注意,当我在布局文件中,为自定义view定义如下内容时,上面代码打印出的是:
 
而在调用onMeasure时,以match_parent为例,最先传入的 widthMeasureSpec和heightMeasureSpec值如下图:

Mode值分别代表:
AT_MOST=-2147483648 (0x80000000) The child can be as large as it wants up to the specified size.
EXACTLY=1073741824 (0x40000000)  :  The parent has determined an exact size for the child. The child is going to be given those bounds regardless of how big it wants to be.
UNSPECIFIED=0 (0x00000000)The parent has not imposed any constraint on the child. It can be whatever size it wants.
通过上面的结果,我们来分析一下:

1.在测量width和height时,重复了四次。也就是说,每个view在onMeasure时,都会调用此方法4次来测量最终放置的位置和大小
2.在使用match_parent,wrap_content以及自定义大小时,Mode和size值会发生变化,说明Layout_width/height会对Mode和size产生影响
3.通过对比match_parent打印出的mode值,在一开始调用onMeasure时,传入的值分别为1073742302和1073742548,而当通过MeasureSpec.getMode计算之后,得到的值均为1073741824。我们把两个值一减,得到的结果是:480和724。好吧,我大胆的猜测,这就是它测量的方法。

以上有忽略或错漏的地方,希望指出!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值