ActionBar 容量/溢出不会随方向变化而变化
我有一个使用 ActionBar 的应用程序,我自己处理方向更改:
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
...菜单应该适合 ActionBar,横向时不会溢出,但纵向时不会溢出:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="@string/Game" android:id="@+id/game" android:icon="@android:drawable/ic_menu_manage" android:showAsAction="ifRoom|withText"/>
<item android:title="@string/Type" android:id="@+id/type" android:icon="@android:drawable/ic_menu_edit" android:showAsAction="ifRoom|withText"/>
<item android:title="@string/Other" android:id="@+id/other" android:icon="@android:drawable/ic_menu_gallery" android:showAsAction="ifRoom|withText"/>
<item android:title="@string/Solve" android:id="@+id/solve" android:icon="@android:drawable/ic_menu_directions" android:showAsAction="ifRoom|withText"/>
<item android:title="@string/Help" android:id="@+id/help" android:icon="@android:drawable/ic_menu_help" android:showAsAction="ifRoom"/>
</menu>
启动时,这可以正常工作:
横向:
肖像: (是的,我可以强制所有项目始终显示并且它们会适合,如下所示,但这可能会在较小的平板电脑上损坏)
当模拟器更改方向时,ActionBar 的容量似乎不会改变:
,当我开始风景时: (这没问题,但不一致)
风景,当我开始肖像时: 这看起来真的很愚蠢,这就是我想解决这个问题的原因。
我将此调用添加到 invalidateOptionsMenu(),但是没有帮助:(
@Override
public void onConfigurationChanged(Configuration newConfig)
{
maybeMoveSomeViewsAround(newConfig);
super.onConfigurationChanged(newConfig);
invalidateOptionsMenu();
}
实际上我为了向后兼容而通过反射调用它,但是调试器告诉我它确实被调用了并且没有遇到一个例外。)
invalidateOptionsMenu() 实际上最终在返回之前调用了 onCreateOptionsMenu() (它重新膨胀了菜单),我可以在后者内部看到 getResources().getConfiguration().orientation 已经改变了。所以这实在是令人费解。如果重新创建选项菜单,当方向改变时,一定是ActionBar本身缓存了宽度?
有没有办法在不破坏/创建 Activity 的情况下重新创建 ActionBar?(因为后者在我的情况下有点昂贵)
编辑:这是一个 最小示例项目显示了该问题。
编辑2:我曾想过检查屏幕宽度并以编程方式在始终和从不之间适当调整showAsAction标志,但这需要知道(或猜测)每个项目的宽度。 ActionBar 的公共 API 在这一点上对我没有帮助。
I have an app using the ActionBar, where I handle orientation changes myself:
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
...and the menu should fit in the ActionBar without overflow in landscape, but not in portrait:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="@string/Game" android:id="@+id/game" android:icon="@android:drawable/ic_menu_manage" android:showAsAction="ifRoom|withText"/>
<item android:title="@string/Type" android:id="@+id/type" android:icon="@android:drawable/ic_menu_edit" android:showAsAction="ifRoom|withText"/>
<item android:title="@string/Other" android:id="@+id/other" android:icon="@android:drawable/ic_menu_gallery" android:showAsAction="ifRoom|withText"/>
<item android:title="@string/Solve" android:id="@+id/solve" android:icon="@android:drawable/ic_menu_directions" android:showAsAction="ifRoom|withText"/>
<item android:title="@string/Help" android:id="@+id/help" android:icon="@android:drawable/ic_menu_help" android:showAsAction="ifRoom"/>
</menu>
On startup, this works correctly:
Landscape:
Portrait:
(yes, I could force all items to always display and they would fit, as shown below, but that might break on a smaller tablet)
When the emulator changes orientation, the ActionBar's capacity doesn't seem to change:
Portrait, when I started in landscape:
(this is ok, but inconsistent)
Landscape, when I started in portrait:
This looks really silly and is the reason I want to fix this.
I added this call to invalidateOptionsMenu(), but it doesn't help:
@Override
public void onConfigurationChanged(Configuration newConfig)
{
maybeMoveSomeViewsAround(newConfig);
super.onConfigurationChanged(newConfig);
invalidateOptionsMenu();
}
(Actually I call it by reflection for backward compatibility, but the debugger tells me it really is called and does not encounter an exception.)
invalidateOptionsMenu() actually ends up calling onCreateOptionsMenu() (which re-inflates the menu) before returning, and I can see inside the latter that getResources().getConfiguration().orientation has already changed. So this is really puzzling. If the options menu is being recreated, when the orientation has changed, it must be ActionBar itself caching the width?
Is there a way to re-create the ActionBar without destroying/creating the Activity? (because the latter is a bit expensive in my case)
Edit: Here's a minimal sample project showing the issue.
Edit 2: I had thought of checking the screen width and programmatically adjusting the showAsAction flags between always and never appropriately, but that requires knowing (or guessing) the width of each item. ActionBar's public API does not help me on that point.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我遇到了这个问题并想出了一个 100% 有效的 hack。
我最终调用了 invalidateOptionsMenu() 两次。看下面的代码:
在你的 onCreateOptionsMenu() 中,在你想要显示的菜单项上设置这个:
不是一个漂亮的解决方案,但它有效。
I ran into this problem to and came up with a hack which works 100%.
I eneded up calling invalidateOptionsMenu() two times. Look at the code below:
And in your onCreateOptionsMenu() set this on you menuitems you want to show:
Not a pretty solution but it works.
我谨慎地解决了这个问题:当设备的宽度大于 850dip 时,强制显示 ActionBar 中的所有项目,否则继续让平台决定。
这是 git 提交。 编辑:和后续提交使用这个领域太新了,哎呀。 :-)
我肯定仍然对更好的答案感兴趣(除了等待平台的修复)。
I've cautiously worked around this: when the device's width is greater than 850dip, force showing all items in the ActionBar, otherwise continue to let the platform decide.
Here's the git commit. Edit: and the follow-up commit to fix using a field that's too new, oops. :-)
I'm definitely still interested in better answers (other than waiting for a fix to the platform).
我发现最简单、最有效的解决方法是清除菜单然后重建它。
例如:
I found that the simplest and most effective workaround was to clear the menu and then rebuild it.
For example: