自定义view --onMerasure

这篇博客详细解释了自定义View中的onMeasure方法,包括如何获取父容器传来的宽度和高度模式及值,以及如何根据模式和比例ratio重新测量尺寸。文中提到了MeasureSpec的EXACTLY和AT_MOST模式,并指出在不同条件下如何调整宽度和高度以满足尺寸需求。最后,展示了如何在XML布局中应用自定义的SmartImageView。
摘要由CSDN通过智能技术生成




  1. // 父容器传过来的宽度方向上的模式  
  2.     int widthMode = MeasureSpec.getMode(widthMeasureSpec);  
  3.     // 父容器传过来的高度方向上的模式  
  4.     int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
  5.   
  6.     // 父容器传过来的宽度的值  
  7.     int width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft()  
  8.             - getPaddingRight();  
  9.     // 父容器传过来的高度的值  
  10.     int height = MeasureSpec.getSize(heightMeasureSpec) - getPaddingLeft()  
  11.             - getPaddingRight();  
  12.   
  13.     if (widthMode == MeasureSpec.EXACTLY  
  14.             && heightMode != MeasureSpec.EXACTLY && ratio != 0.0f) {  
  15.         // 判断条件为,宽度模式为Exactly,也就是填充父窗体或者是指定宽度;  
  16.         // 且高度模式不是Exaclty,代表设置的既不是fill_parent也不是具体的值,于是需要具体测量  
  17.         // 且图片的宽高比已经赋值完毕,不再是0.0f  
  18.         // 表示宽度确定,要测量高度  
  19.         height = (int) (width / ratio + 0.5f);  
  20.         heightMeasureSpec = MeasureSpec.makeMeasureSpec(height,  
  21.                 MeasureSpec.EXACTLY);  
  22.     } else if (widthMode != MeasureSpec.EXACTLY  
  23.             && heightMode == MeasureSpec.EXACTLY && ratio != 0.0f) {  
  24.         // 判断条件跟上面的相反,宽度方向和高度方向的条件互换  
  25.         // 表示高度确定,要测量宽度  
  26.         width = (int) (height * ratio + 0.5f);  
  27.   
  28.         widthMeasureSpec = MeasureSpec.makeMeasureSpec(width,  
  29.                 MeasureSpec.EXACTLY);  
  30.     }  
  31.   
  32.     super.onMeasure(widthMeasureSpec, heightMeasureSpec);  

对于onMeasure方法,有几点需要注意的:

1、父容器传过来的两个参数widthMeasureSpec和heightMeasureSpec,通过MeasureSpec.getMode()来获取参数中的模式,与控件的填充方式都是有对应关系的,这在上一篇博文:Android自定义控件系列七:详解onMeasure()方法中如何测量一个控件尺寸(一)中也有提到过

        ①xml布局文件中的fill_parent或具体值,或者是直接设置控件的LayoutParams中的width和height的具体值或者LayoutParams.FILL_PARENT填充父容器方式,都会对应让上面通过getMode获取参数中的模式为:MeasureSpect.EXACTLY,代表精确取值,因为除了直接指定值之外,填充父容器,也是精确值

  

        ②xml布局文件中设置wrap_content方式或者是在代码中设置LayoutParams.WRAP_CONTENT方式,都会让getMode变成MeasureSpect.AT_MOST


2、对于父容器传过来的高度或者宽度的值,不一定就是控件想要的宽度或者高度的值,这是因为模式不一样,这个值代表的意义也不一样,所以才会需要通过测量来改变高度或者宽度的值来达到想要的效果。

其中,如果是模式是EXACTLY,那么传过来的值就是具体指,也可以说是父容器想要我们的控件变成这个具体的大小。

但是模式如果是AT_MOST,那么传过来的值,就不会是具体的值,一般会是一个最大值,因为AT_MOST代表,不超过多少,那么这个值就是不超过的上限。


3、可以看到我们通过拿到父容器传过来的高度,宽度的模式和值,然后经过两种if-else判断来重新测量值的大小,这两种判断的依据就是:

        ①当宽度确定时(宽度为EXACTLY),高度模式不是EXACTLY时(也即高度不确定时),高度按照ratio的比例来重新测量

        ②当高度确定时(高度为EXACTLY),高度模式不是EXACTLY时(也即高度不确定时),宽度按照ratio的比例来重新测量


4、在测量完毕之后,因为已经得到了想要的宽度或者高度的具体的精确的值,我们再通过MeasureSpec.makeMeasureSpec()方法来调用精确的值和精确的模式,来合成一个宽度/高度方向上的合成值,最后将合成好的值传递给super.onMeasure(widthMeasureSpec, heightMeasureSpec);设置控件为我们想要的大小。


然后我们就可以在XML布局文件中,将之前的ImageView改成:com.example.imageviewdemo.SmartImageView



















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值