首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GalaxyS2、S3和S4上的自定义布局重绘问题

GalaxyS2、S3和S4上的自定义布局重绘问题
EN

Stack Overflow用户
提问于 2014-08-29 02:32:32
回答 1查看 408关注 0票数 2

我有一个自定义布局(扩展FrameLayout),其中包含一些项。每个项目都是一个自定义View,可以加载相应的对象(比如用户的配置文件、显示图片等)。这些视图包含在几个LinearLayout(行)中,这样我就可以在行中正确地排列它们,而不会出现问题。行是固定的(例如,项目0、1、&2总是在第一行并始终存在,3和4在第2行等等)。我使用FrameLayout,因为这些行需要重叠一点.想想交错的六边形。

当布局加载时,由于我还不知道大小,所以所有的行都排列在一起。

代码语言:javascript
复制
protected void onMeasure (final int widthMeasureSpec, final int heightMeasureSpec)

onMeasure方法中,我使用提供的宽度和高度MeasureSpecs来计算我有多少空间。然后在此基础上,计算每个项目的最大宽度和高度,并将其存储在3个变量中(宽度、高度和半径)。我还计算了给定项目之间的填充和间距,布局本身的宽度和高度需要是什么。现在,我获取这些值,并创建新的MeasureSpec,模式设置为MeasureSpec.EXACTLY,并将它们传递给超级布局。

代码语言:javascript
复制
super.onMeasure (MeasureSpec.makeMeasureSpec (width, MeasureSpec.EXACTLY),
                     MeasureSpec.makeMeasureSpec (height, MeasureSpec.EXACTLY));

Note:最初我使用setMeasuredDimension (width, height)来强制布局的大小,但它受到了我将要描述的问题的影响。更改为MeasureSpec.EXACTLY方法修复了它。

代码语言:javascript
复制
protected void onLayout (final boolean changed, final int l, final int t, final int r, final int b)

OnLayout方法中,我使用在onMeasure中计算的值来布局项目。如果changed是假的,我会保释,因为一切都没有改变。否则,我循环遍历行并设置它们的最高边距:

代码语言:javascript
复制
final int rowTop = rowTop(i); // i = index of row
final LayoutParams layoutParams = (LayoutParams) row.getLayoutParams ();
layoutParams.topMargin = rowTop;
layoutParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
row.setLayoutParams (layoutParams);

这允许行重叠一点(数量是根据大小、填充等计算的)。一旦设置了所有行,我就循环遍历项目并设置它们的高度和宽度(用onMeasure计算):

代码语言:javascript
复制
final ViewGroup.LayoutParams layoutParams = child.getLayoutParams ();
layoutParams.width = cellWidth;
layoutParams.height = cellHeight;
child.setLayoutParams (layoutParams);

这在许多设备上都能很好地工作。当我旋转设备时,它会重新计算所有这些值(打印这些值以便我确认),并重新绘制一切都很好。这包括Nexus 4Cyanogenmod-7Cyanogenmod-11LG G3 Stock ROMGalaxy S5。我可以加载其他片段并返回到包含此布局的片段,一切都按预期工作。

然而,由于某些原因,在S2、S3或S4上的事情并不顺利。不幸的是,我不能包括截图(Company IP),但我希望描述这些症状可能会有所帮助。

下面,我说我已经证实了这一点--我的意思是我用纸和铅笔画出物品的比例,看上去是对的。

旋转在有问题的设备上,当我旋转时,正确计算onMeasure值。我已经通过日志,纸和铅笔确认了这一点。onLayout值也被正确计算(验证)。不过,我在屏幕上看到的不是计算值告诉我的。这些值似乎落后于一次旋转。当设备进行横向处理时,我看到了与肖像相同的绘图(除非设备是正方形的,否则不应该发生这种情况)。当我旋转回肖像,我现在看到的项目与景观大小。

reload 当我加载另一个片段(考虑导航抽屉)并使用这个自定义布局重新加载片段时,这些行永远不会扩展到多个行(它们在最初的时候保持完全重叠)。

我在onConfigurationChangedonMeasureonSizeChangedonLayout上有日志输出,它们都在应该时打印并打印出我希望计算的值:

代码语言:javascript
复制
08-28 18:14:41.498  19593-19593/<REDACTED>: config
08-28 18:14:41.518  19593-19593/<REDACTED>: measure
08-28 18:14:41.518  19593-19593/<REDACTED>: Forcing size to 1903x2374
08-28 18:14:41.518  19593-19593/<REDACTED>: measure
08-28 18:14:41.518  19593-19593/<REDACTED>: Forcing size to 1903x2374
08-28 18:14:41.538  19593-19593/<REDACTED>: size
08-28 18:14:41.538  19593-19593/<REDACTED>: layout
08-28 18:14:41.548  19593-19593/<REDACTED>: Top of row 0: 0
08-28 18:14:41.548  19593-19593/<REDACTED>: Top of row 1: 524
08-28 18:14:41.548  19593-19593/<REDACTED>: Top of row 2: 1062
08-28 18:14:41.548  19593-19593/<REDACTED>: Top of row 3: 1601

有人在这些设备上遇到绘图问题吗?我的绘画问题让你想起了你必须处理的事情吗?如果是的话,你是怎么绕过它的?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-09-05 20:09:10

  • View.layout()期间,您应该对每个孩子使用onLayout()

在布局期间,您确实希望定位您的子程序,因此您可以计算它们的相对坐标并调用它们上的layout(),这样他们就可以继续设置各自的mLeftmRight等,并在屏幕上有一个位置。他们的高度和宽度刚刚在量程中计算出来。

在布局传递期间设置LayoutParams看起来有点像黑客,是一个难闻的。你在这里处于较低的水平,你不应该这样做。

您的情况:例如,当您设置一行的边距时。我的想法是,在“无问题”设备上,布局传递会运行两次。在那里你可能会叫super.onLayout()。第一次子区域定位不正确时,(被忽略的)边距计算是正确的。您没有看到这一点,因为在绘制布局之前,会再次触发布局传递(它在RelativeLayout中吗?)因此,FrameLayout.onLayout()根据在第一次布局传递上计算的边距来设置正确的子位置。在某些设备上,布局传递只运行一次,一切都会中断。

如果您想为ViewGroup实现布局通行证,您可能不想调用super.onLayout()。有关实现示例,请参阅常见布局的代码,如FrameLayout。您可以在View文档中阅读有关度量和布局传递的信息。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25560857

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档