android 自定义view onMeasure()


http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1102/1891.html


小知识:如果动态初始化view时没有制定layoutParams ,系统会默认给你生成wrap_content的layoutParams



调用父类onMeasure()

首先定义一个类继承View,重写onMeasure(),并调用父类onMeasure()方法。

 
 
  1. public class MeasureExampleView extends View {
  2. public MeasureExampleView(Context context) {
  3. super(context);
  4. }
  5. public MeasureExampleView(Context context, AttributeSet attrs) {
  6. super(context, attrs);
  7. }
  8. @Override
  9. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  10. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  11. }
  12. }

再定义layout文件,使用MeasureExampleView并设置background,margin与父容器区分。

 
 
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent">
  5. <mzzo.customview.MeasureExampleView
  6. android:background="@android:color/holo_blue_dark"
  7. android:layout_margin="10dp"
  8. android:layout_width="match_parent"
  9. android:layout_height="match_parent" />
  10. </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()时

  1. MeasureExampleView的layout_width以及layout_height属性值 match_parent 或者 wrap_content显示大小由其父容器控件决定。

  2. MeasureExampleView设置为固定的值,就显示该设定的值

怎样重写onMeasure()

示例
 
 
  1. //widthMeasureSpec 和 heightMeasureSpec的值 由父容器决定
  2. @Override
  3. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  4. int width = measureDimension(DEFAULT_WIDTH, widthMeasureSpec);
  5. int height = measureDimension(DEFAULT_HEIGHT, heightMeasureSpec);
  6. setMeasuredDimension(width, height);
  7. }

定义一个方法处理  widthMeasureSpec,heightMeasureSpec的值

 
 
  1. private int measureHanlder(int measureSpec){
  2. int result = defaultSize;
  3. int specMode = MeasureSpec.getMode(measureSpec);
  4. int specSize = MeasureSpec.getSize(measureSpec);
  5. if (specMode == MeasureSpec.EXACTLY) {
  6. result = specSize;
  7. } else if (specMode == MeasureSpec.AT_MOST) {//相当于我们设置为wrap_content
  8. result = Math.min(defaultSize, specSize);
  9. } else {//相当于我们设置为match_parent
  10. result = defaultSize;
  11. }
  12. return result;
  13. }
说明

MeasureSpec.getSize()会解析MeasureSpec值得到父容器width或者height。

MeasureSpec.getMode()会得到三个int类型的值分别为:MeasureSpec.EXACTLY MeasureSpec.AT_MOST,MeasureSpec.UNSPECIFIED。

MeasureSpec.UNSPECIFIED 未指定,所以可以设置任意大小。

MeasureSpec.AT_MOST  MeasureExampleView可以为任意大小,但是有一个上限。比如这种情况

 
 
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent">
  5. <mzzo.customview.MeasureView
  6. android:background="@android:color/holo_blue_dark"
  7. android:layout_margin="10dp"
  8. android:layout_width="wrap_content"
  9. android:layout_height="wrap_content" />
  10. </LinearLayout>

MeasureSpec.EXACTLY 父容器为MeasureExampleView决定了一个大小,MeasureExampleView大小只能在这个父容器限制的范围之内。
比如这种情况:

 
 
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="50dp"
  4. android:layout_height="50dp">
  5. <mzzo.customview.MeasureExampleView
  6. android:background="@android:color/holo_blue_dark"
  7. android:layout_margin="10dp"
  8. android:layout_width="wrap_content"
  9. android:layout_height="wrap_content" />
  10. </LinearLayout>

又或者是这种情况:

 
 
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent">
  5. <mzzo.customview.MeasureView
  6. android:background="@android:color/holo_blue_dark"
  7. android:layout_margin="10dp"
  8. android:layout_width="50dp"
  9. android:layout_height="50dp" />
  10. </LinearLayout>

这样当你使用 android:layout_width|android:layout_height属性为:wrap_content时,MeasureView的大小为默认值 100dpx100dp,你也可以根据自己的规则去重写onMeasure()方法。

小结

  • 重写onMeasure()方法是为了自定义View尺寸的规则

  • 如果你的自定义View的尺寸是根据父控件行为一致,就不需要重写onMeasure()方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值