FrameLayout子视图在调整大小时无法正确更新 [英] FrameLayout child view not updating correctly on resize
问题描述
我有一个Android应用程序,其中的根视图是FrameLayout
,它在旋转时会保留并调整大小,而不是重新创建.
I have an Android application in which the root view is a FrameLayout
which on rotation is kept and resized rather than recreated.
FrameView
的子项中有一个占据整个空间的自定义View
(主视图),另一个我想沿底部边缘显示为窄带的自定义View
(在纵向模式)或右边缘(横向模式).
Among the children of the FrameView
is one custom View
(the main view) that takes up the entire space, and another custom View
which I want to display as a narrow band along the bottom edge (in portrait mode) or the right edge (in landscape mode).
为此,我从主视图的onSizeChanged()
方法运行以下代码:
To this end I run the following code from the main view's onSizeChanged()
method:
boolean isBandShowing = ...; // whether the band should be shown
boolean isPortrait = ...; // whether we are in portrait mode, controls where the band is displayed
int horizontalBandHeight = ...; // default height for band in portrait mode
int verticalBandWidth = ...; // default width for band in landscape mode
bandView.setVisibility(isBandShowing ? View.VISIBLE : View.GONE);
LayoutParams bandLayoutParams = new FrameLayout.LayoutParams(
isPortrait ? LayoutParams.MATCH_PARENT : verticalBandWidth, // X
isPortrait ? horizontalBandHeight : LayoutParams.MATCH_PARENT, // Y
Gravity.BOTTOM | Gravity.RIGHT);
bandView.setLayoutParams(bandLayoutParams);
创建后,onSizeChanged()
被调用一次(在日志输出中可见)并按预期方式设置频段.
Upon creation, onSizeChanged()
gets called once (visible in the log output) and sets up the band as it is supposed to.
但是,旋转显示器时,波段的位置未正确更新.从肖像到风景的第一次旋转后,乐队仍显示在底部.当我旋转回肖像时,乐队会向右移动-一直落后.
When the display is rotated, however, the position of the band is not updated properly. After the first rotation from portrait into landscape, the band still displays at the bottom. When I rotate back into portrait, the band moves to the right – it is consistently lagging behind.
添加一些日志输出,我可以看到以下内容:
Adding some log output, I can see the following:
-
onSizeChanged()
每次旋转都会被调用 - 顶部的四个变量具有正确的值(人像/风景正确反映了新的方向)
- 如果我从新创建的
LayoutParams
中查询宽度和高度,则它们具有预期值 - 如果我在调用
setLayoutParams()
之后立即查询bandView
的尺寸,则它们具有旧值(如旋转之前显示的那样).
onSizeChanged()
gets called on every rotation- the four variables at the top have the correct value (portrait/landscape correctly reflects the new orientation)
- if I query the width and height from the newly created
LayoutParams
, they have the expected values - if I query the dimensions of
bandView
right after the call tosetLayoutParams()
, they have the old values (as displayed before the rotation).
我尝试了一些尝试,但无济于事:
I've tried a few things, to no avail:
- 在
FrameLayout
和波段视图上同时调用requestLayout()
- 同时调用
invalidate()
- 同时调用
postInvalidate()
- 在设置新的
LayoutParams
之前先从FrameLayout
中删除bandView
,然后重新添加
- calling
requestLayout()
on both theFrameLayout
and the band view - calling
invalidate()
on both - calling
postInvalidate()
on both - removing
bandView
from theFrameLayout
before setting the newLayoutParams
, then re-adding it
有什么作用?
推荐答案
正如我根据日志输出所怀疑的那样,在调用onSizeChanged()
时,UI胆量尚未更新.我还没有弄清楚是什么,但是要点是,LayoutParams
的内容需要推迟到其他所有内容都完成之后再进行.可以通过将代码包装到Runnable
并将其post()
封装到FrameLayout
中来完成:
As I had suspected based on the log output, something in the guts of the UI has not been updated by the time onSizeChanged()
gets called. I haven't figured out what, but the takeaway is that the LayoutParams
stuff needs to be deferred until everything else has finished. This can be done by wrapping the code into a Runnable
and post()
ing that to the FrameLayout
:
static boolean isBandShowing = ...; // whether the band should be shown
static boolean isPortrait = ...; // whether we are in portrait mode, controls where the band is displayed
static int horizontalBandHeight = ...; // default height for band in portrait mode
static int verticalBandWidth = ...; // default width for band in landscape mode
frameLayout.post(new Runnable() {
@Override
public void run() {
bandView.setVisibility(isBandShowing ? View.VISIBLE : View.GONE);
LayoutParams bandLayoutParams = new FrameLayout.LayoutParams(
isPortrait ? LayoutParams.MATCH_PARENT : verticalBandWidth, // X
isPortrait ? horizontalBandHeight : LayoutParams.MATCH_PARENT, // Y
Gravity.BOTTOM | Gravity.RIGHT);
bandView.setLayoutParams(bandLayoutParams);
}
});
那解决了.
这篇关于FrameLayout子视图在调整大小时无法正确更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!