自定义view--onMeasure方法的作用

onMeasure:就是来测量设置自定义控件大小的方法。

为什么要重写这个方法?

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

如果只是这样调用,在里面什么都没做,只是super,那么你在xml里设置自定义控件的layout_width和layout_height属性时,使用match_parent或者wrap_content,最终控件的大小是由父控件决定的,一般就是会填充父容器了。

如果你自己设定了具体的值,那么大小就是你设定的值。

那么我们自己设定值不就行了么,也不用那么麻烦的去重写onMeasure方法了。但是,如果你有一天使用这个自定义view时,你想让它使用wrap_content属性,此时你会发现,没有用,和设置match_parent一样。到底为什么会这样呢?

原来是wrap_content和match_parent这两个属性是不指定具体大小的,但是我们把view绘制在屏幕上是需要具体的宽度和高度的,所以如果你没有重写onMeasure方法,自己定义测量大小的算法,那么系统就根据该自定义view的父容器,去设置自定义view的大小。此时不论是wrap_content和或是match_parent,得到的效果都是一样的,而你自己在xml里设置了具体的大小,就会按照你指定的大小绘制显示。

这时你就要你重写onMeasure方法了,自定义自己的测量方法和规则,那么当你没有指定具体的大小,使用wrap_content时,系统会根据你在onMeasure方法里定义的测量方法来测量自定义view,也就能达到你的需求了。

重写时,先得到系统根据你在xml设置的属性,自动测量到的控件大小

final int sizeWdith = MeasureSpec.getSize(widthMeasureSpec);
final int modeWdith = MeasureSpec.getMode(widthMeasureSpec);
final int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
final int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
然后定义width和height变量,用来存放自己真正需要的大小
//根据自己的需求来控件的真实设置大小
int width = 0;
int height = 0;

   再然后,就是一堆自己的算法,比如真实的宽度width = sizeWdith + paddingLeft +paddingRight

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

最后,设置完自己需要的测量方法后,要把自己得到的真实的控件大小设置给控件

setMeasuredDimension(width,height);
这样重写onMeasure方法就完成了


来个简单点的例子:

我们想绘制一个正方形的view,在onMeasure方法里,我们得到系统测量的大小,然后调用了setMeasureDimension方法,宽高取两者中的最小值,这样就确保了宽高一致。

/**
 * 完成对控件的大小的测量
 * @param widthMeasureSpec
 * @param heightMeasureSpec
 */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int width=MeasureSpec.getSize(widthMeasureSpec);
    int height=MeasureSpec.getSize(heightMeasureSpec);
    //让宽高一致,确保是个正方形
    setMeasuredDimension(Math.min(width,height),Math.min(width,height));
}

此时在xml中

<com.example.yd.loadingview.shape.ShapeView
    android:id="@+id/shape_view"
    android:layout_width="match_parent"
    android:layout_height="25dp" />

layout_width和layout_height 如果设置为match_parent或者wrap_content,那么会填充父容器,这点上面已经解释过了,如果layout_width设置为match_parent或者wrap_content,但是layout_height设置了一个具体的值25dp,此时

setMeasuredDimension(Math.min(width,height),Math.min(width,height));
就起作用了,它会限定宽高一致,也就会把 l ayout_width里的match_parent或者wrap_content赋予了和layout_height一样的值,绘制出一个宽高都是25dp的正方形。

如果你没有重写onMeasure方法,只是这样调用

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

<com.example.yd.loadingview.shape.ShapeView
    android:id="@+id/shape_view"
    android:layout_width="match_parent"
    android:layout_height="25dp" />
你得到的就是一个宽度填充父容器,高度为25dp的长方形了。

所以当你没有具体的去指定自定义view的大小时,想通过内容来动态的撑起控件的大小,此时你就要重写onMeasure方法,自己定义测量的规则,你在xml里设置wrap_content,也不会填充父容器了,而是根据你指定的测量方法来设置控件的大小。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值