http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1102/1891.html
调用父类onMeasure()
首先定义一个类继承View,重写onMeasure(),并调用父类onMeasure()方法。
- public class MeasureExampleView extends View {
- public MeasureExampleView(Context context) {
- super(context);
- }
- public MeasureExampleView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
- }
再定义layout文件,使用MeasureExampleView并设置background,margin与父容器区分。
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <mzzo.customview.MeasureExampleView
- android:background="@android:color/holo_blue_dark"
- android:layout_margin="10dp"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
- </LinearLayout>
产生效果如下,不难发现MeasureExampleView充满了父控件
修改layout文件中的MeasureExampleView layout_width以及layout_height属性修改成wrap_content,结果仍然是一样的,就不贴图了。
修改layout文件中LinearLayout(父容器) layout_width以及layout_height属性修改成固定的值比如50dp,产生效果如下。发现 MeasureExampleView 跟随了LinearLayout(父容器)设置的固定大小(50dpx50dp)。
修改layout文件中MeasureExampleView layout_width以及layout_height属性修改成固定的值比如50dp,产生效果如下,发现 MeasureExampleView 的大小为设定的值 50dp x 50dp
结论
重写onMeasure(),并调用父类onMeasure()时
-
MeasureExampleView的layout_width以及layout_height属性值 match_parent 或者 wrap_content显示大小由其父容器控件决定。
-
MeasureExampleView设置为固定的值,就显示该设定的值
怎样重写onMeasure()
示例
- //widthMeasureSpec 和 heightMeasureSpec的值 由父容器决定
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int width = measureDimension(DEFAULT_WIDTH, widthMeasureSpec);
- int height = measureDimension(DEFAULT_HEIGHT, heightMeasureSpec);
- setMeasuredDimension(width, height);
- }
定义一个方法处理 widthMeasureSpec,heightMeasureSpec的值
- private int measureHanlder(int measureSpec){
- int result = defaultSize;
- int specMode = MeasureSpec.getMode(measureSpec);
- int specSize = MeasureSpec.getSize(measureSpec);
- if (specMode == MeasureSpec.EXACTLY) {
- result = specSize;
- } else if (specMode == MeasureSpec.AT_MOST) {//相当于我们设置为wrap_content
- result = Math.min(defaultSize, specSize);
- } else {//相当于我们设置为match_parent
- result = defaultSize;
- }
- return result;
- }
说明
MeasureSpec.getSize()会解析MeasureSpec值得到父容器width或者height。
MeasureSpec.getMode()会得到三个int类型的值分别为:MeasureSpec.EXACTLY MeasureSpec.AT_MOST,MeasureSpec.UNSPECIFIED。
MeasureSpec.UNSPECIFIED 未指定,所以可以设置任意大小。
MeasureSpec.AT_MOST MeasureExampleView可以为任意大小,但是有一个上限。比如这种情况
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <mzzo.customview.MeasureView
- android:background="@android:color/holo_blue_dark"
- android:layout_margin="10dp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- </LinearLayout>
MeasureSpec.EXACTLY 父容器为MeasureExampleView决定了一个大小,MeasureExampleView大小只能在这个父容器限制的范围之内。
比如这种情况:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="50dp"
- android:layout_height="50dp">
- <mzzo.customview.MeasureExampleView
- android:background="@android:color/holo_blue_dark"
- android:layout_margin="10dp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- </LinearLayout>
又或者是这种情况:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <mzzo.customview.MeasureView
- android:background="@android:color/holo_blue_dark"
- android:layout_margin="10dp"
- android:layout_width="50dp"
- android:layout_height="50dp" />
- </LinearLayout>
这样当你使用 android:layout_width|android:layout_height属性为:wrap_content时,MeasureView的大小为默认值 100dpx100dp,你也可以根据自己的规则去重写onMeasure()方法。
小结
-
重写onMeasure()方法是为了自定义View尺寸的规则
-
如果你的自定义View的尺寸是根据父控件行为一致,就不需要重写onMeasure()方法