Is there any option to detect a click in overflow menu?
I don't want to detect clicking in particular items.
As it was posted in this other question, you can do the following:
#Override
public boolean onMenuOpened(int featureId, Menu menu) {
if(featureId == AppCompatDelegate.FEATURE_SUPPORT_ACTION_BAR){
Toast.makeText(this, "OPEN", Toast.LENGTH_SHORT).show();
}
return super.onMenuOpened(featureId, menu);
}
#Override
public void onPanelClosed(int featureId, Menu menu) {
if(featureId == AppCompatDelegate.FEATURE_SUPPORT_ACTION_BAR){
Toast.makeText(this, "CLOSE", Toast.LENGTH_SHORT).show();
}
super.onPanelClosed(featureId, menu);
}
If you are inheriting from AppCompat. If not, the right constant to be used is Window.FEATURE_ACTION_BAR
Are you simply trying to detect when the options menu itself is made visible? If so, I believe the "onPrepareOptionsMenu" method on Activity is your best bet.
Prepare the Screen's standard options menu to be displayed. This is
called right before the menu is shown, every time it is shown. You can
use this method to efficiently enable/disable items or otherwise
dynamically modify the contents.
The default implementation updates the system menu items based on the
activity's state. Deriving classes should always call through to the
base class implementation.
http://developer.android.com/reference/android/app/Activity.html#onPrepareOptionsMenu(android.view.Menu)
Related
So I have this toolbar in my app, and I want to display different menu items depending on whether the user is logged in or not. When the user logs in or out I want to update my layout which for now is the toolbar menu to represent the change. For some reason though, my menu items are not removed at all, all of them are visible at all times, regardless of the login state.
My menu items:
<menu
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_add"
android:icon="#drawable/ic_action_add"
android:title="#string/action_add"
app:showAsAction="ifRoom"/>
<item
android:id="#+id/action_login"
android:icon="#drawable/ic_action_logged_out"
android:title="#string/action_log_in"
app:showAsAction="always"/>
<item
android:id="#+id/action_logout"
android:icon="#drawable/ic_action_logged_in"
android:title="#string/action_log_out"
app:showAsAction="always"/>
</menu>
The first menu item is only supposed to be visible to a user that is logged in. Also I guess it's self explanatory but I only want one of the log in/out buttons to be visible depending on the login state.
My Java code:
protected void initializeToolbar(){
myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
menu = myToolbar.getMenu();
resetToolbarMenu();
myToolbar.setOnMenuItemClickListener(this);
}
private void resetToolbarMenu(){
menu.clear();
getMenuInflater().inflate(R.menu.menu, menu);
if(loginPrefs.getBoolean("login", false)) { //loginPrefs is reference to a SharedPreference object
menu.removeItem(1);
} else {
menu.removeItem(2);
menu.removeItem(0);
}
}
Reason I got two methods is that I only want to set up the toolbar and listener once, but I want to be able to change the menu every time the user logs in/out without reloading the page.
After a successful login the resetToolbarMenu() method will be called again.
I suppose the menu.remove(0) does not update the UI, but I could not find another way to reach my menu object without first inflating it and then getting it from the toolbar, and I assume the inflation is what decides what items are visible. Basically, I could not find a way to remove any menu items before inflating or updating the UI in another way than inflating.
Solution:
I changed my java code into something like this:
protected void initializeToolbar(){
myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
setSupportActionBar(myToolbar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return super.onCreateOptionsMenu(menu); // Don't know if this is necessary or if returning true is prefered.
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
if(loginPrefs.getBoolean("login", false)) {
menu.getItem(0).setVisible(true);
menu.getItem(1).setVisible(false);
menu.getItem(2).setVisible(true);
} else {
menu.getItem(0).setVisible(false);
menu.getItem(1).setVisible(true);
menu.getItem(2).setVisible(false);
}
return true;
}
I also had to call invalidateOptionsMenu() on logout/login to update the toolbar/menu. However onPrepareOptionsMenu() is also automatically called whenever you open the menu for items that aren't shown on the toolbar itself.
PS: OnCreateOptionsMenu and OnPrepareOptionsMenu will not be used unless you remember to setSupportActionBar(myToolbar) as I forgot.
You can create options menu by overriding onCreateOptionsMenu. You can create 2 xml and inflate either one of them depending on your logic. To force a redraw of the menu, you can call invalidateOptionsMenu.
For example
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
if (login) {
inflater.inflate(R.menu.login_menu, menu);
} else {
inflater.inflate(R.menu.logout_menu, menu);
}
return true;
}
And outside change the flag and force redraw
login = false; // or true
invalidateOptionsMenu();
You have to override onPrepareOptionsMenu in the activity to change the items in the menu.
From the documentation:
Prepare the Screen's standard options menu to be displayed. This is called right before the menu is shown, every time it is shown. You can use this method to efficiently enable/disable items or otherwise dynamically modify the contents.
I want to show a Menu when click a specific image :
popup_but = (ImageView) findViewById(R.id.imageView2);
popup_but.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
showmen();
}
});
And the menu :
public void showmen() {
PopupMenu popup = new PopupMenu(First.this, popup_but);
popup.getMenuInflater().inflate(R.menu.popup, popup.getMenu());
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId())
{
case R.id.men1:
//do something
return true;
case R.id.men5:
finish();
return true;
}
return true;
}
});
popup.show();
}
It. works. now i want to do the same when click the hardware menu button. so i use this code :
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
showmen();
}
The problem is here : when menu button clicked it just show menu for the FIRST time
Take a look in the onPrepareOptionsMenu:
On Android 2.3.x and lower, the system calls onPrepareOptionsMenu()
each time the user opens the options menu (presses the Menu button).
On Android 3.0 and higher, the options menu is considered to always be
open when menu items are presented in the action bar. When an event
occurs and you want to perform a menu update, you must call
invalidateOptionsMenu() to request that the system call
onPrepareOptionsMenu().
onCreateOptionsMenu() is called every time the hardware menu button is clicked, and if it returns true each time. What I do is, style the menu items using XML and then inflate the XML inside onCreateOptionsMenu() . Every time I click the hardware menu, the menu is inflated from XML. onPrepareOptionsMenu() is only for when you want to change the menu items during the lifecycle of the app. The problem, I think is in your implementation of showmen(). I think the PopupMenu.OnMenuItemClickListener is called only the first time, not every time.
I want to attach a menu item on click of which a sub menu opens.
I am able to get the output but my menu item always appears in the overflow menu. With some research I found out that setShowAsAction can be used to make it visible on the Action Bar but I can't set them for subMenu item.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
//(this is valid) menu.add("File").setShowAsAction(2);
SubMenu sm = menu.addSubMenu("File");
//(can't do this) sm.setShowAsAction(2);
sm.add("Open");
sm.add("Close");
return true;
}
Use sm.getItem() to get the actual MenuItem for the submenu. You can then call setShowAsAction() on that.
In some methods of my Activity I want to check the title of menu or know if it is checked or not. How can I get Activity's menu. I need something like this.getMenu()
Be wary of invalidateOptionsMenu(). It recreates the entire menu. This has a lot of overhead and will reset embedded components like the SearchView. It took me quite a while to track down why my SearchView would "randomly" close.
I ended up capturing the menu as posted by Dark and then call onPrepareOptionsMenu(Menu) as necessary. This met my requirement without an nasty side effects. Gotcha: Make sure to do a null check in case you call onPrepareOptionsMenu() before the menu is created. I did this as below:
private Menu mOptionsMenu;
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
mOptionsMenu = menu
...
}
private void updateOptionsMenu() {
if (mOptionsMenu != null) {
onPrepareOptionsMenu(mOptionsMenu);
}
}
Call invalidateOptionsMenu() instead of passing menu object around.
you could do it by passing the Menu object to your Activity class
public class MainActivity extends Activity
{
...
...
private Menu _menu = null;
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
_menu = menu;
return true;
}
private Menu getMenu()
{
//use it like this
return _menu;
}
}
There several callback methods that provide menu as a parameter.
You might wanna manipulate it there.
For example:
onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)
onCreateOptionsMenu(Menu menu)
onCreatePanelMenu(int featureId, Menu menu)
There several more, best you take a look in activity documentation and look for your desired method:
http://developer.android.com/reference/android/app/Activity.html
As far as I could understand what you want here is which may help you:
1. Refer this tutorial over option menu.
2. Every time user presses menu button you can check it's title thru getTitle().
3. Or if you want to know the last menu item checked or selected when user has not pressed the menu button then you need to store the preferences when user presses.
Android now has the Toolbar widget which was a Menu you can set/get. Set the Toolbar in your Activity with some variation of setSupportActionBar(Toolbar) for stuff like onCreateOptionsMenu from a Fragment for example. Thread revived!
In Android, I create my menu item like this?
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, 0, 0, "Menu1");
menu.add(0, 1, 0, "Menu2");
return true;
}
How can I set all the menu item disabled programmatically (in another part of the code in my activity, not in onCreateOptionsMenu() method itself)?
You can use the groupId you set to disable/enable all the menu items at once, using menu.setGroupEnabled(). So for example, since you added the items to group 0, you'd do:
menu.setGroupEnabled(0, false);
Also, if you want to dynamically modify the menu, you should hook into onPrepareOptionsMenu(). onCreateOptionsMenu() is only called once per Activity, so it's good for setting up the initial menu structure, but onPrepareOptionsMenu() should be used to enable/disable menus as necessary later in the Activity.
add returns a MenuItem (which you can also retrieve from the Menu object), that you can store away into a variable.
MenuItem menu1;
public boolean onCreateOptionsMenu(Menu menu) {
menu1 = menu.add(0, 0, 0, "Menu1");
}
public void someOtherMethod() {
if(menu1 != null) {
// if it's null, options menu hasn't been created, so nevermind
menu1.setEnabled(false);
}
}
I prefer to hide them completely if they should not be used (instead of disabling them).
For that I do:
menu.clear();
and to recreate it:
invalidateOptionsMenu();
This also works for menu items added from fragments.
If still relevant:
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
for(int i=0; i<menu.size(); i++){
menu.getItem(i).setEnabled(isMenuEnabled);
}
}
and call invalidateOptionsMenu() then isMenuEnabled changed
If you have multiple occasions where you want to do something with all items of a menu (for example changing the 'checked' state) there is an elegant solution using Kotlin Extension Properties:
(Building on top of the answer of Valery)
In one place define the property 'items' of android.view.Menu:
import android.view.Menu
import android.view.MenuItem
val Menu.items: List<MenuItem>
get() {
val items = mutableListOf<MenuItem>()
for (i in 0 until this.size()) {
items.add(this.getItem(i))
}
return items
}
Now you can use it on any menu:
anyMenu.items.forEach { it.isEnabled = false }