2014-12-08 93 views
5

我需要在酒吧下面显示子菜单,而不是在酒吧本身的顶部。Android操作栏子菜单项显示在操作栏顶部而不是在酒吧下方

复制下面

<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> 

我动作条XML在活动(应用程序也有一个抽屉式导航栏)

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

想通了吗? – JackyBoi 2015-04-17 13:44:46

+0

同样的问题在这里(Android 5.1)。在Android开发过程中,经过几年来这些“特性”的磕磕绊绊,我必须说Android是令人沮丧的平台,唉。 – Stan 2015-05-26 12:13:00

回答

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

现在从一开始预计将显示下拉菜单。

+0

最好在onOptionsItemSelected中使用监听器,而不是onPrepareOptionsMenu – JFouad 2016-12-13 11:52:03

+0

@JFouad,我不确定你是否理解这个问题。你的建议是无关紧要的,不要说错。 – Stan 2016-12-14 10:51:28

+0

这是更好地推动这一代码 ' menu.findItem(R.id.menu_sort).setOnMenuItemClickListener(新OnMenuItemClickListener(){ @Override 公共 布尔onMenuItemClick(菜单项项) { popupMenu.show(); return true; } }); ' from onPrepareOptionsMenu to onOptionsItemSelected – JFouad 2016-12-14 13:45:25

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> 

+0

这很好,谢谢! android:overlapAnchor在API级别15(我的目标)不支持,所以我不得不把这个XML放到我的res/values-v21/styles.xml文件中,然后我删除了android:overlapAnchor设置我的正常res/values/styles.xml。这摆脱了错误和警告,现在它工作得很好! – HanClinto 2016-01-19 21:45:54

0

@斯坦的解决方案并没有为我工作,所以这里是我的方式来实现对动作条的顶子菜单(但低于当然的主菜单):
我已创建2个xml文件:menu_main。XMLmenu_more.xml位于在res /菜单目录


第一个 '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(我没有足够的信誉10来显示图像)
在活动中,我重写了这个方法:

公共布尔onPrepareOptionsMenu(菜单菜单)


在前面的方法中,我得到了对主菜单项的引用(在这种情况下是菜单@ + id/action_more位于m enu_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