Android action bar submenu items displayed on top of the action bar and not below the bar

I need to show the submenu under the panel, and not on top of the panel itself.

Copying my xml action bar below

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

In action (the app also has a navigation box)

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

Simply.

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

+3
source

Preamble

As usual, I ran into some strange problem while developing an application for Android, tried to find a solution and landed on this question. As it was in many cases before, there is no answer. Therefore, I was forced to solve the problem from scratch and now posted an answer with my workaround.

Enter

I have an Android application with an action bar and some menu items that need to be expanded using a submenu of the drop-down list. The first attempt was to implement it, as suggested in the documentation for Android. Therefore, I added a new menu item menu_sort to the existing action bar menu and the menu container:

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

Result

The effect was exactly as described in the question: the submenu is displayed on top of the action bar. Here is a screenshot taken on Android 5.1.1:

problem with dropdown submenu on top of its parent action bar

I played with many options and code snippets - nothing helped. Finally, I came to the next

Decision

First, move all the submenus to a separate menu layout, for example menu/sorting.xml , and remove it from the menu_sort item of the main menu (shown above).

Secondly, modify or create an onPrepareOptionsMenu event onPrepareOptionsMenu with the following code:

 @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); } 

Here is the result:

properly positioned dropdown submenu under action bar - workaround

Now the drop-down menu is displayed from the very beginning from the very beginning.

+1
source

@Stan's solution does not work for me, so here is my way to implement a submenu on top of the ActionBar (but, of course, under the main menu):
I created 2 xml files: menu_main.xml and menu_more.xml located in the res / menu directory


The first "menu_main.xml" contains the menu:

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


The second element of 'menu_more.xml' contains a drop-down menu:

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


Here's what the previous menus look like:
result-after-add-2-xmls (I do not have 10 reputation to display the image)
In this operation, I override this method:

public boolean onPrepareOptionsMenu (menu menu)


In the previous method, I get a link to the main menu of the menu (in this case, the menu with @ + id / action_more located in the menu_main.xml file), then setOnMenuItemClickListener on it and, finally, declare and configure the PopupMenu instance to control and display items submenu:

 // 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); 


And here is the final result:
final browse-down menu

0
source

Source: https://habr.com/ru/post/1208560/


All Articles