安卓高手之路 图形系统(4 Measure的算法)
安卓高手之路 图形系统(4 Measure的算法) - 修补C++ - ITeye技术网站
Java代码
- /**
- * 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 us
- case 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 us
- case MeasureSpec.AT_MOST:
- if (childDimension >= 0) {
- // Child wants a specific size... so be it
- resultSize = 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 be
- case MeasureSpec.UNSPECIFIED:
- if (childDimension >= 0) {
- // Child wants a specific size... let him have it
- resultSize = childDimension;
- resultMode = MeasureSpec.EXACTLY;
- } else if (childDimension == LayoutParams.MATCH_PARENT) {
- // Child wants to be our size... find out how big it should
- // be
- resultSize = 0;
- resultMode = MeasureSpec.UNSPECIFIED;
- } else if (childDimension == LayoutParams.WRAP_CONTENT) {
- // Child wants to determine its own size.... find out how
- // big it should be
- resultSize = 0;
- resultMode = MeasureSpec.UNSPECIFIED;
- }
- break;
- }
- return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
- }
/*** 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
的大小。同时,测量方式设置为EXACTLY2.如果当前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的算法)相关推荐
- 安卓高手之路 图形系统(2)----------------基于Binder的架构思路)
在学习安卓的时候最迷惑的就是Binder.图形框架的理解与Binder的理解分不开.前面一篇 [ 安卓高手之路之java层Binder 从代码角度分析了Java层Binder的实现原理.在C++层,这 ...
- 安卓高手之路 图形系统(3 底层SurfceFlinger系统)
底层SurfaceFLinger系统主要通过SurfaceTextureLayer进行绘图信息的传递.整个图花了几天时间,终于有所眉目.希望能给致力于研究SurfaceFlinger架构的人一些参考. ...
- 安卓高手之路之 ClassLoader
我不喜欢那些泛泛而谈的去讲那些形而上学的道理,更不喜欢记那些既定的东西.靠记忆去弥补思考的人,容易陷入人云亦云的境地,最后必定被记忆所围困,而最终消亡的是创造力.希望这个高手之路系列能够记录我学习安卓 ...
- 安卓高手之路之 图形系统之 图形框架(1)
安卓图形系统理解起来并不容易.那是因为系统对于数据的封装非常多,图形模块与输入输出,应用程序管理等模块参杂在一起.让开发者很难摸清其中的脉络.下面先给出最简单的一张图. 这张图 ...
- 安卓高手之路之图形系统(6)ListView继续
综述: 本篇首先介绍了ListView的实现细节.然后介绍了Gallery,ListView,ViewPager的效率对比分析.以及效率低下的原因.最后给出了一些解决方案. 1.在上一篇讨论了requ ...
- 安卓高手之路之图形系统(6)requestLayout的流程
当一个View调用requestLayout的时候,会给当前的View设置一个FORCE_LAYOUT标记.由此向ViewParent请求布局.这样从这个View开始向上一直requestLayout ...
- 安卓高手之路之图形系统【5】安卓ListView和EditText配合使用时的注意事项。
ListView实现滚动和布局时的注意实现: 1.如何实现自动定位到底部: android:stackFromBottom="true" 这样ListView就可以实现从底向上增长 ...
- [置顶] 安卓高手之路之ClassLoader(二)
因为ClassLoader一定与虚拟机的启动有关系,那么必须从Zygote的启动开始看代码.下面就分析一下这些代码,行数不多: int main(int argc, const char* const ...
- [置顶] 安卓高手之路之 WindowManager
安卓中的画面不是纯粹由window组成.而是改成了window+view的组织模式.window是一个顶层窗口的概念.view就相当于在window内的控件.而subwindow则是依附于window ...
最新文章
- 【HDOJ】4343 Interval query
- OEM、ODM、OBM简介 (说一个软件是O出来的 O的含义)
- python 接口数据驱动_python接口测试实例--数据驱动(程序与数据分离)
- 手机耗电统计app_Android O新特性:精确统计APP电量消耗
- DIV+CSS规范命名
- 递归--基于回溯和递归的八皇后问题解法
- webview布局适配实践
- 【CDN】域名无法访问,ping不到,tracert不到
- python编写简单赌博游戏赏析及注意事项
- python颜色表_Python:数据可视化,必须注意的30个小技巧
- SQL数据库中日期时间类型,按日期group by 实现
- 【python】matplotlib绘图显示不了中文,且没有SimHei、FangSong等字体
- 模式识别与机器学习第四章特征选择和提取
- 《IE恶搞迷》扩展功能使用
- Allegro PCB 转 PADS Layout 之后的修修补补
- MediaWiki搭建指导
- 视频怎么去水印教程 视频怎么去水印无痕迹
- noip2011 公交观光
- 华益血糖信息管理系统服务器,华益血糖信息化管理系统
- JAVA IO与NIO优劣浅析