Android操作栏子菜单项显示在操作栏顶部而不是栏下方

时间:2014-12-08 07:07:55

标签: android menu android-actionbar

我需要在栏下方显示子菜单,而不是栏栏本身。

将我的操作栏xml复制到

下面
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
    <item
        android:id="@+id/action_pages"
        android:orderInCategory="1"
        android:showAsAction="withText|always"
        android:icon="@drawable/ic_action_pages"
        android:title="">
        <menu>
            <item android:id="@+id/item1" android:title="Placeholder"></item>
        </menu>
    </item>
</menu>

在活动中(App还有一个导航抽屉)

public boolean onCreateOptionsMenu(Menu menu) {
    if (!mNavigationDrawerFragment.isDrawerOpen()) {
        getMenuInflater().inflate(R.menu.main, menu);
        restoreActionBar();
        return true;
    }
    return super.onCreateOptionsMenu(menu);
}

3 个答案:

答案 0 :(得分:3)

简单。     

<style name="AppTheme" parent="AppBaseTheme">
    <item name="actionOverflowMenuStyle">@style/OverflowMenu</item>
</style>

<style name="OverflowMenu" parent="Widget.AppCompat.PopupMenu.Overflow">
    <!-- Required for pre-Lollipop. -->
    <item name="overlapAnchor">false</item>

    <!-- Required for Lollipop. -->
    <item name="android:overlapAnchor">false</item>
</style>

答案 1 :(得分:1)

<强>序言

像往常一样,我在开发Android应用时遇到了一个奇怪的问题,试图找到解决方案并找到了这个问题。正如之前的许多情况一样,没有答案。所以我被迫从头开始解决问题,现在用我的解决方法发布答案。

<强>输入

我有一个带有操作栏的Android应用程序和一些菜单项,必须使用下拉菜单进行扩展。第一次尝试是按照Android文档的建议实现它。所以我将新菜单项menu_sort添加到现有操作栏菜单和子menu容器中:

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
   <item android:id="@+id/id1" android:icon="@drawable/ic_1"
         android:title="@string/id1" android:showAsAction="withText|always"/>
   ...

  <item
    android:id="@+id/menu_sort"
    android:icon="@drawable/ic_menu_sort_selector"
    android:title="&#x25BE;"
    android:titleCondensed="&#x25BE;"
    android:showAsAction="withText|always">
    <menu>
      <item
            android:id="@+id/menu_sort_by_name"
            android:showAsAction="never"
            android:checkable="true"
            android:checked="true"
            android:title="@string/sort_by_name"/>
      <item
            android:id="@+id/menu_sort_by_priority"
            android:showAsAction="never"
            android:checkable="true"
            android:checked="false"
            android:title="@string/sort_by_priority"/>
      <item
            android:id="@+id/menu_sort_by_memory"
            android:showAsAction="never"
            android:checkable="true"
            android:checked="false"
            android:title="@string/sort_by_memory"/>
    </menu>
  </item>
</menu>

<强>结果

效果与问题中描述的完全相同:子菜单显示在操作栏的顶部。以下是在Android 5.1.1上截取的屏幕截图:

problem with dropdown submenu on top of its parent action bar

我玩了很多选项和代码片段 - 没有任何帮助。最后我来到了以下

<强>解决方案

首先,将所有子菜单移动到单独的菜单布局中,例如menu/sorting.xml,然后将其从主菜单的menu_sort项中移除(如上所示)。

其次,使用以下代码修改或创建onPrepareOptionsMenu事件处理程序:

@Override
public boolean onPrepareOptionsMenu(Menu menu)
{
  // as solution utilizes PopupMenu,
  // take care about older Android versions if necessry
  // if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)

  // here goes most crazy part: we use menu id
  // to retrieve corresponding view, automatically created by OS;
  // imho, this is a hack, and menu item should have getView() method or similar;
  View menuItemView = findViewById(R.id.menu_sort);

  // by the way, menuItemView could probably be null under some circumstances

  // create a popup anchored to the view (menu item)
  final PopupMenu popupMenu = new PopupMenu(this, menuItemView);
  // API 14
  // popupMenu.inflate(R.menu.sorting);
  // API 11 (HONEYCOMB)
  popupMenu.getMenuInflater().inflate(R.menu.sorting, popupMenu.getMenu());

  // process popup clicks as appropriate
  popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener()
  {
    @Override
    public boolean onMenuItemClick(MenuItem item)
    {
      switch(item.getItemId())
      {
        // ... place some code
      }
      return true;
    }
  });

  // bind the popup to the item menu
  menu.findItem(R.id.menu_sort).setOnMenuItemClickListener(new OnMenuItemClickListener()
  {
    @Override
    public boolean onMenuItemClick(MenuItem item)
    {
      popupMenu.show();
      return true;
    }
  });

  return super.onPrepareOptionsMenu(menu);
}

结果如下:

properly positioned dropdown submenu under action bar - workaround

现在,从一开始就按预期显示下拉列表。

答案 2 :(得分:0)

@Stan的解决方案对我不起作用,所以这是我在ActionBar上实现子菜单的方法(当然在主菜单下面):
我创建了2个xml文件:位于res中的 menu_main.xml menu_more.xml / menu目录


第一个'menu_main.xml'包含菜单:

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

<!-- our addMenu doesn't have sub-items-->
<item
    android:id="@+id/action_add"
    android:icon="@drawable/ic_note_add_white_24dp"
    android:title="@string/action_add"
    app:showAsAction="ifRoom"/>

<!-- our moreMenu which show drop-down menu when clicked-->
<item
    android:id="@+id/action_more"
    android:icon="@drawable/ic_more_vert_white_24dp"
    android:title="@string/action_more" <!--in text: "more"-->
    app:showAsAction="always"/>

</menu>


第二个'menu_more.xml'包含下拉菜单:

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

<!-- This menu will be hidden by default-->
<!-- But will be visible when moreMenu with '@+id/action_more' is clicked-->
<item
    android:id="@+id/action_settings"
    app:showAsAction="ifRoom|withText"
    android:title="@string/action_settings" <!-- In text: "Settings"-->
    android:visible="true"/>

</menu>

这是以前的菜单:
result-after-add-2-xmls(我没有足够的声望来显示图像)
在活动中,我已经覆盖了这种方法:

  

public boolean onPrepareOptionsMenu(菜单菜单)

在上一个方法中,我引用了主menuItem(在这种情况下是位于中的 @ + id / action_more 的菜单 menu_main.xml 文件),然后在其上设置 setOnMenuItemClickListener ,最后声明并设置 用于管理和显示子菜单项的PopupMenu 实例:

// show popup menu when menuMore clicked
menu.findItem(R.id.action_more).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
{
    @Override
    public boolean onMenuItemClick(MenuItem item)
    {
        // get reference to menuMore item
        View menuMore = findViewById(item.getItemId());
        // create a popup anchored to the view (menuMore)
        // notes: if declare and set up PopupMenu Outside of this onMenuItemClick()
        // then it'll not work!
        // Because: the view you put into PopupMenu() could be null
        final PopupMenu popupMenu = new PopupMenu(getApplicationContext(), menuMore);
        // inflate 'menu_more.xml' layout file
        // which contain all sub-items of menu
        popupMenu.getMenuInflater().inflate(R.menu.menu_more, popupMenu.getMenu());

        // process popup clicks on sub-items
        popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener()
        {
            @Override
            public boolean onMenuItemClick(MenuItem item)
            {
                switch(item.getItemId()){
                    case R.id.action_settings:
                        Toast.makeText(getApplicationContext(), "showing SettingsActivity..",
                                Toast.LENGTH_SHORT).show();
                        break;
                    // more items go here
                }
                return true;
            }
        });

        popupMenu.show();
        return true;
    }
});

return super.onPrepareOptionsMenu(menu);

这是最终结果:
final-look-drop-down-menu