Android Galaxy S2、S3和S4上的自定义布局重画问题

Android Galaxy S2、S3和S4上的自定义布局重画问题,android,android-layout,android-view,samsung-mobile,Android,Android Layout,Android View,Samsung Mobile,我有一个自定义布局(扩展FrameLayout),其中包含一些项目。每个项目都是一个自定义的视图,可以加载相应的对象(比如用户的配置文件、显示图片等)。这些视图包含在一些LinearLayouts(行)中,因此我可以在行中正确地排列它们,而不会出现问题。行是固定的(例如,项目0、1和2始终位于第一行并始终存在,3和4位于第二行,依此类推)。我使用FrameLayout,因为这些行需要重叠一点。。。想想交错的六边形 加载布局时,所有的行都被放置在彼此的顶部,因为我还不知道它们的大小 protect

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

加载布局时,所有的行都被放置在彼此的顶部,因为我还不知道它们的大小

protected void onMeasure (final int widthMeasureSpec, final int heightMeasureSpec)
onMeasure
方法中,我使用提供的宽度和高度
MeasureSpec
s来计算我有多少空间。然后在此基础上,我计算每个项目可以拥有的最大宽度和高度,并将其存储在3个变量(宽度、高度和半径)中。我还计算了给定项目之间的填充和间距,布局本身需要的宽度和高度。现在,我获取这些值,并创建新的
measurept
s,模式设置为
measurept

super.onMeasure (MeasureSpec.makeMeasureSpec (width, MeasureSpec.EXACTLY),
                     MeasureSpec.makeMeasureSpec (height, MeasureSpec.EXACTLY));
注意:最初我使用
setMeasuredDimension(width,height)
强制调整布局的大小,但它遇到了我将要描述的问题。更改为
MeasureSpec。确切地说
方法修复了它

protected void onLayout (final boolean changed, final int l, final int t, final int r, final int b)
OnLayout
方法中,我使用在
onMeasure
中计算的值来布局项目。如果
changed
为false,我将退出,因为没有任何更改。否则,我将遍历行并设置它们的顶部边距:

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);
这允许行重叠一点(数量根据大小、填充等计算)。设置完所有行后,我将遍历项目并设置它们的高度和宽度(如测量中的
计算):

这在许多设备上都可以正常工作。当我旋转设备时,它会重新计算所有这些值(将它们打印到日志中以便我确认),并重新绘制所有内容。这包括
Nexus 4
Cyanogenmod-7
Cyanogenmod-11
LG G3库存ROM
,以及
Galaxy S5
。我可以加载其他片段并返回到包含此布局的片段,所有内容都按预期工作

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

在下面,我说我已经验证了这一点,我的意思是我用纸和铅笔按比例画了这些项目,看起来很正确

旋转 在有问题的设备上,当我旋转时,
onMeasure
值计算正确。我已经通过日志、纸和铅笔证实了这一点。
onLayout
值也已正确计算(验证)。然而,我在屏幕上看到的并不是计算值告诉我的。这些值似乎落后于一个旋转。当设备变成横向时,我看到的是与纵向相同的图形(除非设备是正方形,否则不应该出现这种情况)。当我旋转回“纵向”时,现在可以看到使用横向尺寸绘制的项目

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

我在
onconfiguration changed
onMeasure
onSizeChanged
onLayout
的开头有日志输出,它们都在应该的时候打印,并打印出我希望计算的值:

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
08-2818:14:41.49819593-19593/:config
08-28 18:14:41.518 19593-19593/:测量
08-28 18:14:41.518 19593-19593/:强制大小为1903x2374
08-28 18:14:41.518 19593-19593/:测量
08-28 18:14:41.518 19593-19593/:强制大小为1903x2374
08-28 18:14:41.538 19593-19593/:尺寸
08-28 18:14:41.538 19593-19593/:布局图
08-28 18:14:41.548 19593-19593/:行顶0:0
08-28 18:14:41.548 19593-19593/:第1行顶部:524
08-28 18:14:41.548 19593-19593/:第2行顶部:1062
08-28 18:14:41.548 19593-19593/:第3行顶部:1601
有人在这些设备上遇到绘图问题吗? 我的绘画问题让你想起了你必须处理的事情吗? 如果是这样的话,你是如何解决的?

  • onLayout()过程中,应在每个子级上使用
    View.layout()
在布局过程中,您确实希望定位您的孩子,因此您可以计算他们的相对坐标并对他们调用
layout()
,以便他们可以继续设置各自的
mLeft
mRight
,等等,并在屏幕上有一个位置。它们的高度和宽度刚刚在测量过程中计算出来

在布局过程中设置
LayoutParams
看起来有点像黑客,是一种臭味。你在这里级别较低,你不应该那样做

您的案例:以设置行边距为例。我的想法是,在“没有问题”的设备上,布局过程运行两次。您可能会在这里调用
super.onLayout()
。第一次未正确定位子项,但正确计算(忽略的)边距时。您看不到这一点,因为在绘制之前,再次触发布局过程(它是否在
RelativeLayout
?)并因此
FrameLayout.onLayout()
根据第一次布局过程中计算的边距设置正确的子位置。在某些设备上,布局过程只运行一次,一切都会中断

如果要为
视图组实施布局过程,请选择y
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