2014-12-08 88 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