即使有足够的空间,showAsAction="ifRoom" 也不显示该项目

Posted

技术标签:

【中文标题】即使有足够的空间,showAsAction="ifRoom" 也不显示该项目【英文标题】:showAsAction="ifRoom" doesn't show the item even when there is plenty of room 【发布时间】:2013-04-01 19:54:30 【问题描述】:

我正在尝试让 ActionBar 在我的应用程序上正常工作(我正在使用 ActionBarSherlock 在 android 2.x 和 4.x 之间获得统一的 UI)。

我觉得android:showAsAction="ifRoom" 只是一个大谎言。每当我将操作设置为ifRoom 时,它总是会出现在溢出菜单中,即使有足够的空间也是如此。这是来自同一个模拟器的两个屏幕截图。第一个显示所有选项设置为always 的ActionBar,第二个显示最后两个选项设置为ifRoom 的ActionBar。如您所见,always 屏幕截图中都显示了它们时有足够的空间,那么为什么它们没有全部显示在第二个中,因为它们确实有空间?

这是我的 menu.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/add"
        android:icon="@drawable/ic_menu_btn_add"
        android:showAsAction="always"
        android:title="Add"/>
    <item
        android:id="@+id/calculateNPV"
        android:icon="@drawable/menu_icon_npv"
        android:showAsAction="always"
        android:title="NPV"/>
    <item
        android:id="@+id/calculateIRR"
        android:icon="@drawable/menu_icon_irr"
        android:showAsAction="always"
        android:title="IRR/YR"/>
    <item
        android:id="@+id/send"
        android:icon="@android:drawable/ic_menu_share"
        android:showAsAction="always"
        android:title="@string/share_pdf"/>
    <item
        android:id="@+id/graph"
        android:icon="@drawable/ic_menu_gallery"
        android:showAsAction="ifRoom"
        android:title="@string/view_cashflow_diagram"/>
    <item
        android:id="@+id/deleteReorder"
        android:icon="@drawable/ic_menu_clear_playlist"
        android:showAsAction="ifRoom"
        android:title="@string/delete_reorder_cashflows"/>

</menu>

【问题讨论】:

【参考方案1】:

希望我来参加聚会还不算太晚。

这真的不是一个大谎言,而是一个小小的疏忽。

showAsAction 属性必须使用不同的命名空间"http://schemas.android.com/apk/res-auto" 定义

因此,您应该在顶部菜单标签中定义一个命名空间,如下所示 xmlns:app="http://schemas.android.com/apk/res-auto"

然后用它来定义你的 showAsAction 属性,像这样 app:showAsAction="ifRoom"

应该可以解决的

【讨论】:

我遇到了完全相同的问题 - 事实上在我的情况下 - 我必须做完全相反的事情:使用 android:showAsAction 命名空间来解决这个问题。 如果你使用ActionBarActivity,你需要使用命名空间。使用 Activity 你可以使用 android:showAsAction 我试过了,不适合我。 Android 文档甚至不支持它。 @KurtCobain 使用android 命名空间解决了我的问题! 如果你使用appcompat库,你需要使用app。否则你应该使用android【参考方案2】:

这是因为指定了应该转到操作栏的最大项目数,它似乎是 4。当然,您可以通过设置 showAsAction: always 来强制它们出现,但关于 google API 指南:

如果您认为您的菜单项中有四个以上是合理的 作为行动项目,那么你应该仔细考虑他们的相对 重要性级别并尝试设置不超过四个作为操作项 (并使用“ifRoom”值来允许系统放置一些 当小屏幕上的空间有限时,返回溢出菜单)。 即使宽屏幕上有可用空间,也不应创建 一长串的操作项使 UI 变得杂乱无章,看起来像一个 桌面工具栏,因此请尽量减少操作项的数量。

此外,以下操作不应显示为操作 项目:设置、帮助、反馈或类似内容。始终将它们保存在 溢出菜单。

【讨论】:

并不总是 4。请参阅此图表:developer.android.com/design/media/action_bar_pattern_table.png 但是正如你所看到的,这些操作是有空间的,所以 -ifRoom- 是一个很大的谎言。 :) 同样令人沮丧的是,没有可见的指示符表明“菜单”按钮还有更多可用选项。向他们显示一些选项(但并非所有选项都没有指示符)要糟糕得多,因为显示 SOME 会告诉用户这是要查看的位置。为什么会有另一个位置? @Jake Wharton:对对对!我知道我以前见过这样的东西,但我不记得在哪里。现在我认为它是在 Google 设计的关于 ActionBar 的动作视频之一中......谢谢! @Kenny Wyland:看这个youtube.com/watch?v=jes1iXRFRw0 它应该能解释一些事情。除了“按钮”之外,ActionBar 上还可以有其他东西。我同意物理菜单按钮的事情,并且没有指示有更多项目。 Jake Wharton:对于我的回答中引用的上下文和规则,我提供了设计指南中相关页面的链接:developer.android.com/design/patterns/actionbar.html【参考方案3】:

补充 Michal Z. 的答案: Android Design Guide Page Patterns->Actionbar 在“Action Buttons”一章中说:

http://developer.android.com/design/patterns/actionbar.html

主操作栏中可以容纳多少操作?操作栏容量由以下规则控制:

主操作栏中的操作按钮不得超过栏宽度的 50%。 底部操作栏上的操作按钮可以使用整个宽度。 以与密度无关的像素 (dp) 为单位的屏幕宽度决定了适合主操作栏的项目数: 小于 360 dp = 2 个图标 360-499 dp = 3 个图标 500-599 dp = 4 个图标 600 dp 及以上 = 5 个图标

【讨论】:

【参考方案4】:

使用app:showAsAction="always" 代替android:showAsAction="always"

【讨论】:

【参考方案5】:

使用

<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:yourapp="http://schemas.android.com/apk/res-auto" >

【讨论】:

请解释您的答案,因为只有代码的答案通常不清楚且难以理解。【参考方案6】:

ActivityBar 力求不超过一定数量的可见元素。而且这个限制确实低于 ActivityBar 可以包含的。限制在 android.support.v7.view.ActionBarPolicy 类中设置:

`/**
     * Returns the maximum number of action buttons that should be permitted within an action
     * bar/action mode. This will be used to determine how many showAsAction="ifRoom" items can fit.
     * "always" items can override this.
     */
    public int getMaxActionButtons() 
        final Resources res = mContext.getResources();
        final int widthDp = ConfigurationHelper.getScreenWidthDp(res);
        final int heightDp = ConfigurationHelper.getScreenHeightDp(res);
        final int smallest = ConfigurationHelper.getSmallestScreenWidthDp(res);

    if (smallest > 600 || widthDp > 600 || (widthDp > 960 && heightDp > 720)
            || (widthDp > 720 && heightDp > 960)) 
        // For values-w600dp, values-sw600dp and values-xlarge.
        return 5;
     else if (widthDp >= 500 || (widthDp > 640 && heightDp > 480)
            || (widthDp > 480 && heightDp > 640)) 
        // For values-w500dp and values-large.
        return 4;
     else if (widthDp >= 360) 
        // For values-w360dp.
        return 3;
     else 
        return 2;
    
`

如您所见,限制在 2 到 5 之间,并且取决于屏幕宽度。

我还没有找到改变这种行为的方法。所以如果你想超过限制,你应该使用 showAsAction="always" 或者为 ActionBar 创建你自己的视图。

【讨论】:

【参考方案7】:

使用下面的代码它将始终有效

<menu 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" 
    tools:context=".MainActivity">
    <item 
        android:id="@+id/menu_share" 
        android:title="Share"
        android:orderInCategory="100" 
        app:showAsAction="ifRoom"
        android:actionProviderClass="android.widget.ShareActionProvider"/>
</menu>

【讨论】:

Insted 使用 android:actionProviderClass="android.widget.ShareActionProvider"/> 使用 app:actionProviderClass="android.support.v7.widget.ShareActionProvider"/>【参考方案8】:

实际上,Android 最多会显示 5 个按钮,包括菜单,但您可以根据需要覆盖该行为。

请记住,Material 设计准则是工具栏上的按钮数量有限。请记住,即使有空间,某些操作也不应该显示为按钮。

但是,如果您有一些有意义的具体操作,即使您总共有 5 个以上,您也可以展示它们。你只需要自己检查屏幕宽度。

首先,在菜单定义中,将“始终”用于您希望始终显示的最多 4 个按钮。对所有其他人使用“从不”,包括那些您可能以编程方式显示为图标的人。

然后,覆盖 onPrepareOptionsMenu 以添加逻辑以强制将更多操作显示为按钮。

@Override
public boolean onPrepareOptionsMenu(Menu menu) 
    final Configuration config = getResources().getConfiguration();
    final int width = config.screenWidthDp;

    if (width > 400) 
        MenuItem item = menu.findItem(R.id.your_action);
        item.setShowAsAction(SHOW_AS_ACTION_ALWAYS);

        item = menu.findItem(R.id.another_action);
        item.setShowAsAction(SHOW_AS_ACTION_ALWAYS);
    

    return super.onPrepareOptionsMenu(menu);

您也可以在方向改变时动态执行此操作,因为横向模式下通常有足够的空间,尤其是在平板电脑上。

    @Override
    public void onConfigurationChanged(@NonNull Configuration newConfig) 
        super.onConfigurationChanged(newConfig);

        invalidateOptionsMenu();
    

但不要弄乱工具栏。记得在小型设备上进行测试。

【讨论】:

以上是关于即使有足够的空间,showAsAction="ifRoom" 也不显示该项目的主要内容,如果未能解决你的问题,请参考以下文章

即使有足够的空间可用于单词,UILabel 自动换行功能也会留下空间

Android中app:showASAction的值及含义

当有足够的空间时,UILabel 自动换行会在下一行添加额外的单词

sparklyr中的堆空间不足,但有足够的内存

树莓派外部安装的 NTFS 磁盘上没有足够的可用空间

谈谈-showAsAction