自定义view--onMeasure方法的作用
2018-01-11 10:53
477 查看
onMeasure:就是来测量设置自定义控件大小的方法。
为什么要重写这个方法?
如果只是这样调用,在里面什么都没做,只是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设置的属性,自动测量到的控件大小
然后定义width和height变量,用来存放自己真正需要的大小
再然后,就是一堆自己的算法,比如真实的宽度width = sizeWdith + paddingLeft +paddingRight
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
最后,设置完自己需要的测量方法后,要把自己得到的真实的控件大小设置给控件
这样重写onMeasure方法就完成了
来个简单点的例子:
我们想绘制一个正方形的view,在onMeasure方法里,我们得到系统测量的大小,然后调用了setMeasureDimension方法,宽高取两者中的最小值,这样就确保了宽高一致。
此时在xml中
layout_width和layout_height 如果设置为match_parent或者wrap_content,那么会填充父容器,这点上面已经解释过了,如果layout_width设置为match_parent或者wrap_content,但是layout_height设置了一个具体的值25dp,此时
就起作用了,它会限定宽高一致,也就会把layout_width里的match_parent或者wrap_content赋予了和layout_height一样的值,绘制出一个宽高都是25dp的正方形。
如果你没有重写onMeasure方法,只是这样调用
你得到的就是一个宽度填充父容器,高度为25dp的长方形了。
所以当你没有具体的去指定自定义view的大小时,想通过内容来动态的撑起控件的大小,此时你就要重写onMeasure方法,自己定义测量的规则,你在xml里设置wrap_content,也不会填充父容器了,而是根据你指定的测量方法来设置控件的大小。
为什么要重写这个方法?
@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));
就起作用了,它会限定宽高一致,也就会把layout_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,也不会填充父容器了,而是根据你指定的测量方法来设置控件的大小。
相关文章推荐
- [Android自定义View] 计算View尺寸方法onMeasure()
- 自定义View_onDraw,onMeasure方法
- 自定义View中的方法onMeasure,onLayout,onDraw作用
- Android填坑之旅(第十四篇)关于软键盘弹出未及时隐藏导致自定义View的onMeasure方法测量错误引发的血案
- android 自定义View之View的测量(onMeasure()方法)
- 自定义View相关可以重写的方法及作用 需要注意的事项
- android 自定义view 里onMeasure方法里使用getWidth()=0
- loadView不需要调用super view,原因:loadView方法的作用就是自定义view.[super loadView]会耗性能.
- 自定义View,关于onMeasure方法的两个参数widthMeasureSpec,heightMeasureSpec
- 自定义View-onMeasure()方法
- 自定义View(三)之View类的onMeasure方法详解
- 第04天实战技术(14):UICollectionView自定义布局方法
- Android利用Paint自定义View实现进度条控件方法示例
- Android 自定义 view(三)—— onDraw 方法理解
- iOS开发学习之利用系统远程UITableView 自定义滑动删除按钮、增加自定义滑动按钮方法
- 自定义View构造方法的推荐写法
- 解析在Android中为TextView增加自定义HTML标签的实现方法
- 自定义ViewGroup基础巩固1---理解onLayout()方法
- Android自定义View的实现方法,带你一步步深入了解View(四)
- 高德地图上显示自定义View方法