安卓高手之路 图形系统(4 Measure的算法) - 修补C++ - ITeye技术网站

Java代码  
  1. /**
  2. * Does the hard part of measureChildren: figuring out the MeasureSpec to
  3. * pass to a particular child. This method figures out the right MeasureSpec
  4. * for one dimension (height or width) of one child view.
  5. *
  6. * The goal is to combine information from our MeasureSpec with the
  7. * LayoutParams of the child to get the best possible results. For example,
  8. * if the this view knows its size (because its MeasureSpec has a mode of
  9. * EXACTLY), and the child has indicated in its LayoutParams that it wants
  10. * to be the same size as the parent, the parent should ask the child to
  11. * layout given an exact size.
  12. *
  13. * @param spec The requirements for this view
  14. * @param padding The padding of this view for the current dimension and
  15. *        margins, if applicable
  16. * @param childDimension How big the child wants to be in the current
  17. *        dimension
  18. * @return a MeasureSpec integer for the child
  19. */
  20. public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
  21. int specMode = MeasureSpec.getMode(spec);
  22. int specSize = MeasureSpec.getSize(spec);
  23. int size = Math.max(0, specSize - padding);
  24. int resultSize = 0;
  25. int resultMode = 0;
  26. switch (specMode) {
  27. // Parent has imposed an exact size on us
  28. case MeasureSpec.EXACTLY:
  29. if (childDimension >= 0) {
  30. resultSize = childDimension;
  31. resultMode = MeasureSpec.EXACTLY;
  32. } else if (childDimension == LayoutParams.MATCH_PARENT) {
  33. // Child wants to be our size. So be it.
  34. resultSize = size;
  35. resultMode = MeasureSpec.EXACTLY;
  36. } else if (childDimension == LayoutParams.WRAP_CONTENT) {
  37. // Child wants to determine its own size. It can't be
  38. // bigger than us.
  39. resultSize = size;
  40. resultMode = MeasureSpec.AT_MOST;
  41. }
  42. break;
  43. // Parent has imposed a maximum size on us
  44. case MeasureSpec.AT_MOST:
  45. if (childDimension >= 0) {
  46. // Child wants a specific size... so be it
  47. resultSize = childDimension;
  48. resultMode = MeasureSpec.EXACTLY;
  49. } else if (childDimension == LayoutParams.MATCH_PARENT) {
  50. // Child wants to be our size, but our size is not fixed.
  51. // Constrain child to not be bigger than us.
  52. resultSize = size;
  53. resultMode = MeasureSpec.AT_MOST;
  54. } else if (childDimension == LayoutParams.WRAP_CONTENT) {
  55. // Child wants to determine its own size. It can't be
  56. // bigger than us.
  57. resultSize = size;
  58. resultMode = MeasureSpec.AT_MOST;
  59. }
  60. break;
  61. // Parent asked to see how big we want to be
  62. case MeasureSpec.UNSPECIFIED:
  63. if (childDimension >= 0) {
  64. // Child wants a specific size... let him have it
  65. resultSize = childDimension;
  66. resultMode = MeasureSpec.EXACTLY;
  67. } else if (childDimension == LayoutParams.MATCH_PARENT) {
  68. // Child wants to be our size... find out how big it should
  69. // be
  70. resultSize = 0;
  71. resultMode = MeasureSpec.UNSPECIFIED;
  72. } else if (childDimension == LayoutParams.WRAP_CONTENT) {
  73. // Child wants to determine its own size.... find out how
  74. // big it should be
  75. resultSize = 0;
  76. resultMode = MeasureSpec.UNSPECIFIED;
  77. }
  78. break;
  79. }
  80. return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
  81. }
 /*** Does the hard part of measureChildren: figuring out the MeasureSpec to* pass to a particular child. This method figures out the right MeasureSpec* for one dimension (height or width) of one child view.** The goal is to combine information from our MeasureSpec with the* LayoutParams of the child to get the best possible results. For example,* if the this view knows its size (because its MeasureSpec has a mode of* EXACTLY), and the child has indicated in its LayoutParams that it wants* to be the same size as the parent, the parent should ask the child to* layout given an exact size.** @param spec The requirements for this view* @param padding The padding of this view for the current dimension and*        margins, if applicable* @param childDimension How big the child wants to be in the current*        dimension* @return a MeasureSpec integer for the child*/public static int getChildMeasureSpec(int spec, int padding, int childDimension) {int specMode = MeasureSpec.getMode(spec);int specSize = MeasureSpec.getSize(spec);int size = Math.max(0, specSize - padding);int resultSize = 0;int resultMode = 0;switch (specMode) {// Parent has imposed an exact size on uscase MeasureSpec.EXACTLY:if (childDimension >= 0) {resultSize = childDimension;resultMode = MeasureSpec.EXACTLY;} else if (childDimension == LayoutParams.MATCH_PARENT) {// Child wants to be our size. So be it.resultSize = size;resultMode = MeasureSpec.EXACTLY;} else if (childDimension == LayoutParams.WRAP_CONTENT) {// Child wants to determine its own size. It can't be// bigger than us.resultSize = size;resultMode = MeasureSpec.AT_MOST;}break;// Parent has imposed a maximum size on uscase MeasureSpec.AT_MOST:if (childDimension >= 0) {// Child wants a specific size... so be itresultSize = childDimension;resultMode = MeasureSpec.EXACTLY;} else if (childDimension == LayoutParams.MATCH_PARENT) {// Child wants to be our size, but our size is not fixed.// Constrain child to not be bigger than us.resultSize = size;resultMode = MeasureSpec.AT_MOST;} else if (childDimension == LayoutParams.WRAP_CONTENT) {// Child wants to determine its own size. It can't be// bigger than us.resultSize = size;resultMode = MeasureSpec.AT_MOST;}break;// Parent asked to see how big we want to becase MeasureSpec.UNSPECIFIED:if (childDimension >= 0) {// Child wants a specific size... let him have itresultSize = childDimension;resultMode = MeasureSpec.EXACTLY;} else if (childDimension == LayoutParams.MATCH_PARENT) {// Child wants to be our size... find out how big it should// beresultSize = 0;resultMode = MeasureSpec.UNSPECIFIED;} else if (childDimension == LayoutParams.WRAP_CONTENT) {// Child wants to determine its own size.... find out how// big it should beresultSize = 0;resultMode = MeasureSpec.UNSPECIFIED;}break;}return MeasureSpec.makeMeasureSpec(resultSize, resultMode);}

这个Measure算法主要是算child的测量方式和大小的。主要根据两种根据:

1. 自身的测量方式(MeasureSpec EXACTLY,AT_MOST,UNSPECIFIED)【这个是parent传过来的】
2. 自身的大小 【这个是parent传过来的】
3. 自己的padding【计算得到】
4. child的大小【child的LayoutParam得到】

根据以上四个推测出child的MeasureSpec 。也就是大小和测量方式。

child的请求大小来确定到底child应该有多宽以及应该怎么测量。

下面的逻辑比较多。

1.如果当前View是Exactly。那么也就是说有了固定的大小。
  
  那么Child如果说是一个固定的LayoutParam.width 或者 height,那么返回结果resultSize 就设置为这个固定值。

如果child是wrapContent,那么resultSize 就设置为当前这个View的工作区大小。也就是去除pad和margin
  的大小。同时,测量方式设置为AT_MOST

如果child是match_parent,那么由于当前View是固定大小的。那么resultSize 就设置为当前这个View的工作区大小。也就是去除pad和margin
  的大小。同时,测量方式设置为EXACTLY

2.如果当前View是MeasureSpec.AT_MOST。也就是说有个最大值。也是这三种情况
  a.fixed
     这个时候,当前View可以无限大,并且child有个固定值。那么就设置这个值吧。   这个地方
,没有做越界判断,因此有时候会出现一个子View非常大,撑破了父View的情况。google在这里
算不算是一个bug呢?也就是当前的currrentView为wrap_content.但是parentView却有一个fixed value。 同时,childView也有一个fixed Value。这个时候,如果childView的大小超过了parentView。 则会出现childView显示不全的现象。
  b.wrap_content
    
     同理,传入AT_MOST.但是不超过当前View的大小。【这个是与当前View为EXACTLY的情况一样】
    
  c.fill_parent

这种情况也非常奇怪。发生在
currentView是wrap_content.而childView是fill_parent的情况。这个时候就没办法搞了。
这个时候,就告诉子View你也没有固定的大小。也就是说循环依赖产生了。唯一的办法是让childView 继续wrap_content.也就是废掉这个fill_parent。从而打破了这种循环依赖。

转载于:https://www.cnblogs.com/seven1979/p/4369631.html

安卓高手之路 图形系统(4 Measure的算法)相关推荐

  1. 安卓高手之路 图形系统(2)----------------基于Binder的架构思路)

    在学习安卓的时候最迷惑的就是Binder.图形框架的理解与Binder的理解分不开.前面一篇 [ 安卓高手之路之java层Binder 从代码角度分析了Java层Binder的实现原理.在C++层,这 ...

  2. 安卓高手之路 图形系统(3 底层SurfceFlinger系统)

    底层SurfaceFLinger系统主要通过SurfaceTextureLayer进行绘图信息的传递.整个图花了几天时间,终于有所眉目.希望能给致力于研究SurfaceFlinger架构的人一些参考. ...

  3. 安卓高手之路之 ClassLoader

    我不喜欢那些泛泛而谈的去讲那些形而上学的道理,更不喜欢记那些既定的东西.靠记忆去弥补思考的人,容易陷入人云亦云的境地,最后必定被记忆所围困,而最终消亡的是创造力.希望这个高手之路系列能够记录我学习安卓 ...

  4. 安卓高手之路之 图形系统之 图形框架(1)

    安卓图形系统理解起来并不容易.那是因为系统对于数据的封装非常多,图形模块与输入输出,应用程序管理等模块参杂在一起.让开发者很难摸清其中的脉络.下面先给出最简单的一张图.             这张图 ...

  5. 安卓高手之路之图形系统(6)ListView继续

    综述: 本篇首先介绍了ListView的实现细节.然后介绍了Gallery,ListView,ViewPager的效率对比分析.以及效率低下的原因.最后给出了一些解决方案. 1.在上一篇讨论了requ ...

  6. 安卓高手之路之图形系统(6)requestLayout的流程

    当一个View调用requestLayout的时候,会给当前的View设置一个FORCE_LAYOUT标记.由此向ViewParent请求布局.这样从这个View开始向上一直requestLayout ...

  7. 安卓高手之路之图形系统【5】安卓ListView和EditText配合使用时的注意事项。

    ListView实现滚动和布局时的注意实现: 1.如何实现自动定位到底部: android:stackFromBottom="true" 这样ListView就可以实现从底向上增长 ...

  8. [置顶] 安卓高手之路之ClassLoader(二)

    因为ClassLoader一定与虚拟机的启动有关系,那么必须从Zygote的启动开始看代码.下面就分析一下这些代码,行数不多: int main(int argc, const char* const ...

  9. [置顶] 安卓高手之路之 WindowManager

    安卓中的画面不是纯粹由window组成.而是改成了window+view的组织模式.window是一个顶层窗口的概念.view就相当于在window内的控件.而subwindow则是依附于window ...

最新文章

  1. 【HDOJ】4343 Interval query
  2. OEM、ODM、OBM简介 (说一个软件是O出来的 O的含义)
  3. python 接口数据驱动_python接口测试实例--数据驱动(程序与数据分离)
  4. 手机耗电统计app_Android O新特性:精确统计APP电量消耗
  5. DIV+CSS规范命名
  6. 递归--基于回溯和递归的八皇后问题解法
  7. webview布局适配实践
  8. 【CDN】域名无法访问,ping不到,tracert不到
  9. python编写简单赌博游戏赏析及注意事项
  10. python颜色表_Python:数据可视化,必须注意的30个小技巧
  11. SQL数据库中日期时间类型,按日期group by 实现
  12. 【python】matplotlib绘图显示不了中文,且没有SimHei、FangSong等字体
  13. 模式识别与机器学习第四章特征选择和提取
  14. 《IE恶搞迷》扩展功能使用
  15. Allegro PCB 转 PADS Layout 之后的修修补补
  16. MediaWiki搭建指导
  17. 视频怎么去水印教程 视频怎么去水印无痕迹
  18. noip2011 公交观光
  19. 华益血糖信息管理系统服务器,华益血糖信息化管理系统
  20. JAVA IO与NIO优劣浅析

热门文章

  1. linux 安装rpm no key,yum 安装报 关于Public key for *.rpm is not installed 的解决方法
  2. 如何将自己写的verilog模块封装成IP核(一)
  3. 如何让Keil MDK兼容Keil C51?
  4. 运放使用中不稳定怎么办?
  5. anaconda卸载重装matplotlib
  6. 联想平板电脑win10如何取消触摸键盘按键声音
  7. python导入自定义模块和路径问题
  8. chocolatey的使用
  9. DOS 和 Linux 常用命令的对比
  10. 将二维序列变为一维度序列进行预测的设计