2019独角兽企业重金招聘Python工程师标准>>>

在自定义View和ViewGroup的时候,我们经常会遇到int型的 MeasureSpec 来表示一个组件的大小,这个变量里面不仅有组件的尺寸大小,还有大小的模式。

这个大小的模式,有点难以理解。在系统中组件的大小模式有三种:

1.精确模式(MeasureSpec.EXACTLY)

在这种模式下,尺寸的值是多少,那么这个组件的长或宽就是多少。

2.最大模式(MeasureSpec.AT_MOST)

这个也就是父组件,能够给出的最大的空间,当前组件的长或宽最大只能为这么大,当然也可以比这个小。

3.未指定模式(MeasureSpec.UNSPECIFIED)

这个就是说,当前组件,可以随便用空间,不受限制。

可能有很多人想不通,一个int型整数怎么可以表示两个东西(大小模式和大小的值),一个int类型我们知道有32位。而模式有三种,要表示三种状  态,至少得2位二进制位。于是系统采用了最高的2位表示模式。如图:

最高两位是00的时候表示"未指定模式"。即MeasureSpec.UNSPECIFIED

最高两位是01的时候表示"'精确模式"。即MeasureSpec.EXACTLY

最高两位是11的时候表示"最大模式"。即MeasureSpec.AT_MOST

很多人一遇到位操作头就大了,为了操作简便,于是系统给我提供了一个MeasureSpec工具类。

这个工具类有四个方法和三个常量(上面所示)供我们使用:

//这个是由我们给出的尺寸大小和模式生成一个包含这两个信息的int变量,这里这个模式这个参数,传三个常量中的一个。

public static int makeMeasureSpec(int size, int mode)

//这个是得到这个变量中表示的模式信息,将得到的值与三个常量进行比较。

public static int getMode(int measureSpec)

//这个是得到这个变量中表示的尺寸大小的值。

public static int getSize(int measureSpec)

//把这个变量里面的模式和大小组成字符串返回来,方便打日志

public static String toString(int measureSpec)

MeasureSpec.EXACTLY:当我们将控件的layout_width或layout_height指定为具体数值时如andorid:layout_width="50dip",或者为FILL_PARENT是,都是控件大小已经确定的情况,都是精确尺寸。

MeasureSpec.AT_MOST是最大尺寸,当控件的layout_width或layout_height指定为WRAP_CONTENT时,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可。因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。

MeasureSpec.UNSPECIFIED是未指定尺寸,这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式。

因此,在重写onMeasure方法时要根据模式不同进行尺寸计算。下面代码就是一种比较典型的方式:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    setMeasuredDimension(getMeasuredLength(widthMeasureSpec, true), getMeasuredLength(heightMeasureSpec, false));
}    private int getMeasuredLength(int length, boolean isWidth) {    int specMode = MeasureSpec.getMode(length);    int specSize = MeasureSpec.getSize(length);    int size;    int padding = isWidth ? getPaddingLeft() + getPaddingRight()    : getPaddingTop() + getPaddingBottom();    if (specMode == MeasureSpec.EXACTLY) {    size = specSize;    } else {    size = isWidth ? padding + mWave.length / 4 : DEFAULT_HEIGHT    + padding;    if (specMode == MeasureSpec.AT_MOST) {    size = Math.min(size, specSize);    }    }    return size;
}

解决ScrollView嵌套ListView和GridView冲突的方法

public class MyListView extends ListView {public MyListView(Context context) {super(context);}public MyListView(Context context, AttributeSet attrs) {super(context, attrs);}public MyListView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,MeasureSpec.AT_MOST);super.onMeasure(widthMeasureSpec, expandSpec);}
}public class MyGridView extends GridView {   private boolean haveScrollbar = true;   public MyGridView(Context context) {   super(context);   }   public MyGridView(Context context, AttributeSet attrs) {   super(context, attrs);   }   public MyGridView(Context context, AttributeSet attrs, int defStyle) {   super(context, attrs, defStyle);   }   /**  * 设置是否有ScrollBar,当要在ScollView中显示时,应当设置为false。 默认为 true  *   * @param haveScrollbars  */   public void setHaveScrollbar(boolean haveScrollbar) {   this.haveScrollbar = haveScrollbar;   }   @Override   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {   if (haveScrollbars == false) {   int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);  super.onMeasure(widthMeasureSpec, expandSpec);   } else {   super.onMeasure(widthMeasureSpec, heightMeasureSpec);   }   }
}

转载于:https://my.oschina.net/qiuhoude/blog/410809

MeasureSpec学习 - 转相关推荐

  1. MeasureSpec学习

    在自定义View和ViewGroup的时候,我们经常会遇到int型的MeasureSpec来表示一个组件的大小,这个变量里面不仅有组件的尺寸大小,还有大小的模式. 这个大小的模式,有点难以理解.在系统 ...

  2. 那些年收藏的技术文章(一) CSDN篇

    #Android ##Android基础及相关机制 Android Context 上下文 你必须知道的一切 Android中子线程真的不能更新UI吗? Android基础和运行机制 Android任 ...

  3. 那些年收藏的技术文章(一)-CSDN篇

    Android Android基础及相关机制 Android View体系 Android坐标相关 Android事件机制及相关问题 Android官方组件 Android Service Andro ...

  4. 【学习】Android中View的工作原理(上)——ViewRoot、DecorView、MeasureSpec

    初识ViewRoot和DecorView ViewRoot对应于ViewRootImpl类,它是连接WindowManager和DecorView的纽带,View的三大流程均是通过ViewRoot完成 ...

  5. Android开源中国客户端学习 (自定义View)左右滑动控件ScrollLayout

    左右滑动的控件我们使用的也是非常多了,但是基本上都是使用的viewpager 等 android基础的控件,那么我们有么有考虑过查看他的源码进行定制呢?当然,如果你自我感觉非常好的话可以自己定制一个, ...

  6. 红橙Darren视频笔记 流式布局tagLayout measure layout方法学习 adapter使用 学习感悟

    效果: 自定义View public class TagLayout extends ViewGroup {private static final String TAG = "TagLay ...

  7. android自定义View学习(二)----自定义绘图

    自定义绘图 自定义视图中最重要的部分是它的外观.根据您的应用需求,自定义绘图可以很容易或复杂.本篇涵盖了一些最常见的操作 onDraw() 绘制自定义视图中最重要的步骤是重写该onDraw()方法.参 ...

  8. 解决Android学习之ScollView嵌套ListView和GridView问题

    Android学习之ScollView嵌套ListView和GridView问题,gridview与这种写法一样 import android.content.Context; import andr ...

  9. Android学习之——ListView下拉刷新

    背景知识 ListView使用非常广泛,对于使用ListView的应用来说,下拉刷新是必不可少要实现的功能. 我们常用的微博.网易新闻,搜狐新闻都使用了这一功能,如下图所示.     微博 搜狐新闻 ...

最新文章

  1. LetCode 70. Climbing Stairs--动态规划-爬梯子--递归等解法
  2. 关于事件相关电位SSVEP应用于视频游戏的研究
  3. VS2013常用快捷方式
  4. aop简介-aop相关概念
  5. sort和qsort函数的用法
  6. (61)FPGA译码器实现(function)
  7. Ubuntu 系统进不去 左上角减号
  8. 数据分析融入至BI工具的新思路
  9. thymeleaf判断对象是否为空的相关逻辑处理
  10. CryptoJS与C#AES加解密互转
  11. 国外设计素材网址干货
  12. 实变函数(4)--Lebesgue积分
  13. Self-assessment Checklists of HSK
  14. Ubuntu 20.04 离线安装podman
  15. NVIDIA GeForce RTX 3080 with CUDA capability sm_86 is not compatible with the current PyTorch
  16. 用计算机丧失了大脑,《心理科》您真的需要大脑“升级”吗? 将大脑视为计算机是有缺...
  17. 江民KV2008离线包和安装包下载 2007-12-24
  18. 绝地求生——PUBG吃鸡游戏模糊,画质很差
  19. ConViT:使用软卷积归纳偏置改进视觉变换器
  20. linux中exp命令详解_exp/imp命令的介绍和使用

热门文章

  1. UNIX(多线程):01---线程简介及线程限制
  2. C++:15---异常机制
  3. Linux线程池的设计
  4. STL源码剖析 queue队列概述
  5. Android WebView 使用漏洞
  6. 25岁肥胖!美研究:晚年恐出现病态肥胖
  7. OpenCL 第5课:向量相加
  8. Patrick Wyatt:代码没问题 程序却有bug?
  9. 手机厂商探路互联网:硬件高利润时代已成历史
  10. springCloud - 第4篇 - 消费者调用服务 ( Feign )