Android操作栏未显示溢出菜单

90
我有一个应用程序中的操作栏,其中包含3个项目。
由于空间问题,只能显示2个项目,因此我希望第一个项目被显示,其余项目则在溢出菜单中显示。然而实际上只有前两个项目被显示,也无法检测到溢出。
以下是相关代码: list_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/menu_insert"
    android:icon="@android:drawable/ic_menu_add"
    android:title="@string/menu_insert" 
    android:showAsAction="ifRoom|withText"/>
<item android:id="@+id/menu_call"
    android:icon="@android:drawable/ic_menu_call"
    android:title="@string/menu_call" 
    android:showAsAction="ifRoom|withText"/>
<item android:id="@+id/menu_agenda"
    android:icon="@android:drawable/ic_menu_agenda"
    android:title="@string/menu_agenda" 
    android:showAsAction="ifRoom|withText"/>
</menu>

Activity.java

public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater mi = getMenuInflater();
    mi.inflate(R.menu.list_menu, menu);
    return true;
}

120
你的设备如果有菜单按钮,溢出图标就不会显示。你用的是什么设备? - Reinier
1
我正在测试的虚拟设备确实有一个菜单按钮,点击它后,缺失的项目出现了,谢谢! - Mats Raemen
2
@Reinier 我正在使用ActionBarSherlock。在运行2.3的Galaxy Ace上它被显示,在运行4.0的Galaxy SII上它没有被显示。两者都有硬件菜单按钮。 - Mister Smith
2
我想确认这让我感到困惑,我在Nexus 7上看到了溢出图标,但在Galaxy Note II上却没有。Note有一个菜单按钮。谢谢! - bsautner
@Reinier,请帮帮我,我遇到了同样的问题该怎么办? - rupesh
显示剩余4条评论
9个回答

125
如果您想显示三个点,无论设备菜单按钮如何! 那么您可以在应用程序类的onCreate方法中调用此方法-
private void makeActionOverflowMenuShown() {
    //devices with hardware menu button (e.g. Samsung Note) don't show action overflow menu
    try {
        ViewConfiguration config = ViewConfiguration.get(this);
        Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
        if (menuKeyField != null) {
            menuKeyField.setAccessible(true);
            menuKeyField.setBoolean(config, false);
        }
    } catch (Exception e) {
        Log.d(TAG, e.getLocalizedMessage());
    }
}

33
这是一个可怕的黑客行为,会破坏平台上其他应用程序的一致性。请勿这样做。 - adamp
19
这似乎是两害相权取其轻。当前的行为是不可接受的。 - biorbnA
6
这是一个很好的方式,可以允许有溢出,菜单硬按键不再被容忍。 - Necronet
5
很好用!即使用户按下硬件菜单按钮(这太棒了),它仍然可以正常工作,尽管你会听到菜单音效两次...有人知道如何让它只播放一次声音吗? - Bruce
5
这不是黑客行为。开发人员需要知道什么被称为黑客行为,因为在Android中这不仅仅是2+2的问题。反射是利用Java机制来节省时间,否则你将不得不全天候向内部类传递上下文或者无限自定义AOSP。对我来说,这个解决方案解决了必须重写和包含大量AOSP自定义内容以及链接私有关联的问题,只为了追求纯净。你知道吗,不能强制启用快速滚动以保持一致性?在使用反射之前,这要求我复制10多个AOSP资源,只为了进行一个字符的编辑。 - leRobot
显示剩余6条评论

54

输出

操作栏

res/menu/menu.xml

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

    <!-- Search / will display always -->
    <item
        android:id="@+id/action_search"
        android:icon="@drawable/ic_action_search"
        android:showAsAction="always"
        android:title="@string/action_search"/>

    <!-- Location Found -->
    <item
        android:id="@+id/action_location_found"
        android:icon="@drawable/ic_action_location_found"
        android:showAsAction="always"
        android:title="@string/action_location_found"/>

    <!-- More -->
    <item
        android:id="@+id/a_More"
        android:icon="@drawable/ic_action_overflow"
        android:showAsAction="always"
        android:title="More">
        <menu>

            <!-- Refresh -->
            <item
                android:id="@+id/action_refresh"
                android:icon="@drawable/ic_action_refresh"
                android:showAsAction="never"
                android:title="@string/action_refresh"/>

            <!-- Help -->
            <item
                android:id="@+id/action_help"
                android:icon="@drawable/ic_action_help"
                android:showAsAction="never"
                android:title="@string/action_help"/>

            <!-- Check updates -->
            <item
                android:id="@+id/action_check_updates"
                android:icon="@drawable/ic_action_refresh"
                android:showAsAction="never"
                android:title="@string/action_check_updates"/>
        </menu>
    </item>

</menu>

MainActivity.java

->

MainActivity.java

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
  
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
 
        return super.onCreateOptionsMenu(menu);
    }

}

下载操作栏图标集


2
看一下@Reinier的评论,他说得对:“如果你的设备有一个菜单按钮,溢出图标就不会显示”。 - Ahmad Dwaik 'Warlock'
你在哪个设备上测试过它?我使用了一台Neo V Xperia和S#。 - Ahmad Dwaik 'Warlock'
已在三星Galaxy S Duos GT-S7562上进行测试。 - Kirit Vaghela
1
注意:展开溢出菜单的项目必须设置showAsAction="always"。 - Kirit Vaghela
1
showAsAction在旧版SDK中的android命名空间中不可用。请访问http://developer.android.com/training/basics/actionbar/adding-buttons.html以克服此问题。在添加此NS http://schemas.android.com/apk/res-auto 后,上述技巧对我非常有效。 - chedine
显示剩余4条评论

42
我知道这不是溢出菜单,但是它很相似。 好的,这很简单,但很难想到。
您首先需要一个要用作溢出充气机的菜单项。 例如:
<item
        android:id="@+id/a_More"
        android:icon="@drawable/more"
        android:showAsAction="always"
        android:title="More">
        </item>

一旦你拥有了你的物品,就添加一个子菜单,其中包含你想要放在溢出菜单中的物品。 例如:

<item
    android:id="@+id/a_More"
    android:icon="@drawable/more"
    android:showAsAction="always"
    android:title="More">
    <menu>
        <item
            android:id="@+id/aM_Home"
            android:icon="@drawable/home"
            android:title="Home"/>
    </menu>
</item>

点击此按钮将展开其它项目。我的应用程序正在使用ActionBarSherlock 4.0,因此在此功能可用之前,您需要访问"SplitActionBar"。(默认的Android ActionBar仍然可以使用)

步骤如下: 在AndroidManifest.xml文件中,在您需要溢出菜单的活动下添加以下代码。

android:uiOptions="splitActionBarWhenNarrow"

注意: 你的项目必须使用 showAsAction="always" 来扩展溢出菜单。

恭喜!现在你已经有了一个溢出菜单!希望我能帮到你 :)


3
好的解决方案,比菜单按钮黑客更好。 - ol0

26
在配有硬件菜单按钮的设备上(例如 Galaxy S3,正如三星所坚持的那样......),溢出菜单的行为类似于“传统”菜单,通过使用硬件菜单按钮来实现。

2
旧的答案,但是使用兼容库后,我们发现了非常奇怪的结果:3个带有硬件按钮的设备,Note 3 Neo = 显示溢出菜单,菜单按钮不起作用,Note 1 = 没有溢出,菜单按钮可以使用,Galaxy S3 = 没有溢出,菜单按钮不起作用!这太疯狂了。 - 3c71

5
当您提到“overflow”菜单时,是指在末尾显示三个点以表示有更多项目的菜单吗?还是指在底部显示溢出项的拆分操作栏?
如果您是指拆分操作栏,请将其添加到活动的清单文件中。
android:uiOptions="splitActionBarWhenNarrow"

默认情况下,三个点的溢出菜单应该自动出现,因此很难从上面提供的信息中确定问题所在。


我是指那三个点。这不是因为项目的原因,因为无论何时更改订单项目,都会显示前两个图标。 - Mats Raemen
我需要提供额外的信息才能确定实际问题吗? - Mats Raemen
你的minSdkVersion、targetSdkVersion和你正在测试的版本是什么? - Sparky
5
您的设备是否有物理菜单按钮,还是像 Galaxy Nexus 手机一样使用虚拟按钮?我认为如果您的手机有物理按钮,则只会显示三个点。 - wnafee

5

要在ActionbarCompat上始终显示操作溢出(三个点):
在菜单文件中,例如:
main.xml

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

    <item
        android:id="@+id/action_settings"
        android:title="@string/action_settings"
        app:showAsAction="never"/>
    <item
        android:id="@+id/action_about"
        android:title="@string/action_about"
        app:showAsAction="never"/>

</menu>

并且在活动文件中:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    return super.onCreateOptionsMenu(menu);
}

这对我来说运行得很好。
已在Google Nexus S和Samsung S3上进行了测试。


3
似乎在带有菜单按钮的设备上,溢出菜单不会显示在ActionBar中。此外,在API level 14(4.0+)之前,我们没有办法知道设备是否有硬件菜单按钮。
此解决方案向android.support.v7.app.ActionBar添加了一个溢出按钮,仅在Honeycomb之前(<3.0)打开标准选项菜单,否则将其留给系统。在任何情况下,您都可以选择所有操作的alwaysifRoom之间。
Action Bar Icon Pack获取溢出图标。
添加一个菜单(我省略了一些不相关的部分,如标题、排序等)。
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">

<item
    android:id="@+id/action_overflow"
    android:orderInCategory="100"
    android:icon="@drawable/ic_action_overflow"
    app:showAsAction="always" />

<item
    android:id="@+id/action_first"
    app:showAsAction="always" />

<item
    android:id="@+id/action_second"
    app:showAsAction="ifRoom" />

</menu>

在3.0+版本中移除我们的溢出操作

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        menu.removeItem(R.id.action_overflow);
    }
    return super.onPrepareOptionsMenu(menu);
}

最后从溢出操作中调用Activity.openOptionsMenu()
额...不行。您不能从菜单按钮调用openOptionsMenu()...但如果您使用AndroidAnnotations,则可以轻松完成:
@OptionsItem
void action_overflow() {
    openOptionsMenuDeferred();
}

@UiThread
void openOptionsMenuDeferred() {
    openOptionsMenu();
}

如果不是这样,我想你应该做类似这样的事情。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == id.action_overflow) {
        openOptionsMenuDeferred();
        return true;
    }
}

private Handler handler = new Handler(Looper.getMainLooper());
public void openOptionsMenuDeferred() {
    handler.post(new Runnable() {
        @Override
        public void run() {
            openOptionsMenu();
        }
    }
    );
}

2
尝试将应用程序的主题从Theme.AppCompat.Light.DarkActionBar更改为Theme.AppCompat.Light。

2

在菜单标签中添加xmlns:your_app_name="http://schemas.android.com/apk/res-auto",并使用your_app_name:showAsAction="always"代替android:showAsAction="always"

例如:

<item
    android:id="@+id/action_search"
    android:icon="@drawable/icon_search"
    android:title="@string/search"
    your_app_name:showAsAction="ifRoom"/>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接