原文:http://tryenough.com/android-...

Android系统控件无法满足我们的需求,因此有必要自定义View。具体方法参见官方开发文档:http://developer.android.com/guide/topics/ui/custom-components.html

MeasureSpec的简介

MesureSpec可以理解为测量View大小的依据。它由一个32位的int值组成,前两位表示测量模式,后30位表示大小值

测量模式(Mode)的类型有3种:UNSPECIFIED、EXACTLY 和
AT_MOST。

原文:http://tryenough.com/android-...

Measure源码分析

public class MeasureSpec {// 进位大小 = 2的30次方// int的大小为32位,所以进位30位 = 使用int的32和31位做标志位private static final int MODE_SHIFT = 30;  // 运算遮罩:0x3为16进制,10进制为3,二进制为11// 3向左进位30 = 11 00000000000(11后跟30个0)  // 作用:用1标注需要的值,0标注不要的值。因1与任何数做与运算都得任何数、0与任何数做与运算都得0private static final int MODE_MASK  = 0x3 << MODE_SHIFT;  // UNSPECIFIED的模式设置:0向左进位30 = 00后跟30个0,即00 00000000000// 通过高2位public static final int UNSPECIFIED = 0 << MODE_SHIFT;  // EXACTLY的模式设置:1向左进位30 = 01后跟30个0 ,即01 00000000000public static final int EXACTLY = 1 << MODE_SHIFT;  // AT_MOST的模式设置:2向左进位30 = 10后跟30个0,即10 00000000000public static final int AT_MOST = 2 << MODE_SHIFT;  /*** makeMeasureSpec()方法* 作用:根据提供的size和mode得到一个详细的测量结果,即measureSpec**/ public static int makeMeasureSpec(int size, int mode) {  return size + mode;  // measureSpec = size + mode;此为二进制的加法 而不是十进制// 设计目的:使用一个32位的二进制数,其中:32和31位代表测量模式(mode)、后30位代表测量大小(size)// 例如size=100(4),mode=AT_MOST,则measureSpec=100+10000...00=10000..00100  }  /*** getMode()方法* 作用:通过measureSpec获得测量模式(mode)**/    public static int getMode(int measureSpec) {  return (measureSpec & MODE_MASK);  // 即:测量模式(mode) = measureSpec & MODE_MASK;  // MODE_MASK = 运算遮罩 = 11 00000000000(11后跟30个0)//原理:保留measureSpec的高2位(即测量模式)、使用0替换后30位// 例如10 00..00100 & 11 00..00(11后跟30个0) = 10 00..00(AT_MOST),这样就得到了mode的值}  /*** getSize方法* 作用:通过measureSpec获得测量大小size**/       public static int getSize(int measureSpec) {  return (measureSpec & ~MODE_MASK);  // size = measureSpec & ~MODE_MASK;  // 原理类似上面,即 将MODE_MASK取反,也就是变成了00 111111(00后跟30个1),将32,31替换成0也就是去掉mode,保留后30位的size  } }

原文:http://tryenough.com/android-...

MeasureSpec值的计算

子view的大小(MeasureSpec值)由父view的MeasureSpec值 和 子view的LayoutParams属性 共同决定,具体计算逻辑封装在getChildMeasureSpec()里.

/*** 源码分析:getChildMeasureSpec()* 作用:根据父视图的MeasureSpec & 布局参数LayoutParams,计算单个子View的MeasureSpec* 注:子view的大小由父view的MeasureSpec值 和 子view的LayoutParams属性 共同决定**/public static int getChildMeasureSpec(int spec, int padding, int childDimension) {  //参数说明* @param spec 父view的详细测量值(MeasureSpec) * @param padding view当前尺寸的的内边距和外边距(padding,margin) * @param childDimension 子视图的布局参数(宽/高)//父view的测量模式int specMode = MeasureSpec.getMode(spec);     //父view的大小int specSize = MeasureSpec.getSize(spec);     //通过父view计算出的子view = 父大小-边距(父要求的大小,但子view不一定用这个值)   int size = Math.max(0, specSize - padding);  //子view想要的实际大小和模式(需要计算)  int resultSize = 0;  int resultMode = 0;  //通过父view的MeasureSpec和子view的LayoutParams确定子view的大小  // 当父view的模式为EXACITY时,父view强加给子view确切的值//一般是父view设置为match_parent或者固定值的ViewGroup switch (specMode) {  case MeasureSpec.EXACTLY:  // 当子view的LayoutParams>0,即有确切的值  if (childDimension >= 0) {  //子view大小为子自身所赋的值,模式大小为EXACTLY  resultSize = childDimension;  resultMode = MeasureSpec.EXACTLY;  // 当子view的LayoutParams为MATCH_PARENT时(-1)  } else if (childDimension == LayoutParams.MATCH_PARENT) {  //子view大小为父view大小,模式为EXACTLY  resultSize = size;  resultMode = MeasureSpec.EXACTLY;  // 当子view的LayoutParams为WRAP_CONTENT时(-2)      } else if (childDimension == LayoutParams.WRAP_CONTENT) {  //子view决定自己的大小,但最大不能超过父view,模式为AT_MOST  resultSize = size;  resultMode = MeasureSpec.AT_MOST;  }  break;  // 当父view的模式为AT_MOST时,父view强加给子view一个最大的值。(一般是父view设置为wrap_content)  case MeasureSpec.AT_MOST:  // 道理同上  if (childDimension >= 0) {  resultSize = childDimension;  resultMode = MeasureSpec.EXACTLY;  } else if (childDimension == LayoutParams.MATCH_PARENT) {  resultSize = size;  resultMode = MeasureSpec.AT_MOST;  } else if (childDimension == LayoutParams.WRAP_CONTENT) {  resultSize = size;  resultMode = MeasureSpec.AT_MOST;  }  break;  // 当父view的模式为UNSPECIFIED时,父容器不对view有任何限制,要多大给多大// 多见于ListView、GridView  case MeasureSpec.UNSPECIFIED:  if (childDimension >= 0) {  // 子view大小为子自身所赋的值  resultSize = childDimension;  resultMode = MeasureSpec.EXACTLY;  } else if (childDimension == LayoutParams.MATCH_PARENT) {  // 因为父view为UNSPECIFIED,所以MATCH_PARENT的话子类大小为0  resultSize = 0;  resultMode = MeasureSpec.UNSPECIFIED;  } else if (childDimension == LayoutParams.WRAP_CONTENT) {  // 因为父view为UNSPECIFIED,所以WRAP_CONTENT的话子类大小为0  resultSize = 0;  resultMode = MeasureSpec.UNSPECIFIED;  }  break;  }  return MeasureSpec.makeMeasureSpec(resultSize, resultMode);  }

总结:
当父view的模式为UNSPECIFIED时(多见于ListView、GridView ),父容器不对view有任何限制,要多大给多大。此情况比较少见,这里不展开讨论,下面总结其余两种情况:

  • 1.子View指定大小值时:

Mode = MeasureSpec.EXACTLY;
Size = 指定的大小

  • 2.子View指定为MATCH_PARENT时:

Mode = 父View此时的模式;
Size = 父View的大小 - padding

  • 3.子View指定为WRAP_CONTENT时:

Mode = AT_MOST;
Size = 父View的大小 - padding, 即父View中剩余的空间

原文:http://tryenough.com/android-...

Android-MeasureSpec那些事相关推荐

  1. Android实战--糗事

    一 .走进安卓世界 1 安卓发展历程 安卓 系统 发展历程 1.1 2008 9月 android 第一版本 1.5 2009年 4 月 30 Cupcake 纸杯蛋糕 拍摄 播放 上传youtube ...

  2. 我想谈谈关于Android面试那些事,一篇文章帮你解答

    开头 通常作为一个Android APP开发者,我们并不关心Android的源代码实现,不过随着Android开发者越来越多,企业在筛选Android程序员时越来越看中一个程序员对于Android底层 ...

  3. 程序员深度学习!我想谈谈关于Android面试那些事,附赠课程+题库

    想要成为一名优秀的Android开发,你需要一份完备的知识体系,在这里,让我们一起成长为自己所想的那样~. 25%的面试官会在头5分钟内决定面试的结果 60%的面试官会在头15分钟内决定面试的结果 一 ...

  4. 我想谈谈关于Android面试那些事,聪明人已经收藏了!

    前言 九月裸辞从长沙跑到上海,跑了一个月的面试,本月中旬终于拿到了爱奇艺的高级工程师offer. 做Android开发整4年有余,但是这一年才是最充实的,我花一年时间努力,送给了自己一个完美的蜕变! ...

  5. Iphone/Android开发囧事

    正在参与的项目是手机客户端(iphone/android)请求服务器的业务模式, 早上iphone同事问起我,说到"为什么wifi连接网络能从服务器192.168.1.****中获取数据,而 ...

  6. Android应用“今日事今日毕”发布了

    今日事今日毕,这是高效工作的最重原则. 没有什么能比从待办事项列表里划掉一些条目更让人觉得舒服的事了. 做为一个高效的人,您需要一个优秀的待办事项管理工具,一个优秀的待办事项列表可以帮助你更加高效的完 ...

  7. ios跟手android吧,这种事,人家还是喜欢用右手 | 涂手 #ios #Android

    在这个全民社交的年代,打着校园.婚恋.约会.图片.文学.艺术等title进行社交的产品越来越多.随着不同群体社交需求的不同,社交产品的脑洞也无限大.今天小编给大家推荐的就是一款小众确十分有趣的涂鸦社交 ...

  8. 安卓是java ios c_如何为Android和iOS使用相同的C ++代码?

    更新. 这个答案在我写完四年后很受欢迎,在这四年里,很多事情都发生了变化,所以我决定更新我的答案以更好地适应我们当前的现实. 答案的想法没有改变; 实施已经改变了一点. 我的英语也发生了变化,它已经有 ...

  9. Android Camera简单整理(一)-Camera Android架构(基于Q)

    Camera整体架构简单整理 一.Android Camera整体架构简述 1.1 Android Camera 基本分层 1.2 Android Camera工作大体流程 二. Camera App ...

  10. (4.6.31)Android Bitmap 详解

    文章目录 一.从相册加载一张图片 1.1 打开相册加载图片 1.2 根据Uri得到Bitmap 二.Bitmap 内存计算方式 2.1 density 和 densityDpi 2.2 getByte ...

最新文章

  1. Window下git生成SSH Key以及格式转换
  2. 图元和片元_OpenGL中的顶点、 图元、片元、像素的含义
  3. HttpServletRequest的方法详细说明
  4. EfficientPS:目前排名第一的高效高精度全景分割算法
  5. Madagascar中的宏定义函数--绝对值函数和符号函数
  6. s905各种型号的区别_2020榨汁机推荐,榨汁机、原汁机和破壁机有什么区别?高性价比榨汁机、原汁机怎么选?...
  7. JAVA并发之多线程基础(3)
  8. scala 基础入门
  9. ( 4 )MySQL中的数据类型(字符串类型)
  10. java arraydeque poll,Java ArrayDeque pollLast()方法
  11. 32获取外部中断状态_STM8单片机中断的主要功能解析
  12. 记录一下weui文档地址
  13. 【生信技能树】GEO数据库挖掘 P6 5了解矩阵
  14. 2022-2023丰田bZ4X维修手册电路图TOYOTA技术资料
  15. Allegro Pad Designer焊盘制作指南
  16. 软件设计师真题知识点笔记❀
  17. 名片小程序制作公司要如何选择?
  18. 微信群里的这几类人,真让人想打他
  19. C#技术分享【Word转换成图片和PDF——2种方案】
  20. 深度学习自学第四周:近几年的经典神经网络结构

热门文章

  1. codesmith学习总结
  2. (重要)java都是值传递,与对象形参所指向的对象改变,其实参所指向的对象也相应改变并不矛盾(2011年9.30日一天写的两个程序的总结结果)...
  3. ThinkPHP 目录结构
  4. dp_c_区间dp_g
  5. [HEOI2015] 兔子与樱花
  6. jsencrypt加密
  7. mongoDB删除某个字段(key)
  8. SVN如何将版本库url访问地址中的https改为http
  9. WPF之坑——ICommandSource与RoutedUICommand
  10. javaweb之Java基础加强