Change option menu's items on item selection - android

I'm trying to change the option menu after an item on the menu is selected.
This is what I tried:
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
if(refresh) {
menu.clear();
menu.add(0, Menu.FIRST, 0, "Changed item");
}
return super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.refresh)
{
refresh = true;
closeOptionsMenu();
invalidateOptionsMenu();
openOptionsMenu();
}
return super.onOptionsItemSelected(item);
}
But I get:
W/InputManagerService(192): Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy#4147c778
and the code is not working..
Any idea?

the menu will close and not reopen, only if i reclick on the menu button i see the new value
I don't know of anyway to keep the options menu open after an item has been selected, however you can reopen it automatically with a Handler and Runnable.
Create a couple new field variables:
private Handler handler = new Handler();
private Runnable reopenMenu = new Runnable() {
#Override
public void run() {
openOptionsMenu();
}
};
And inside onOptionsItemSelected() use:
if(item.getItemId() == R.id.refresh)
{
refresh = true;
invalidateOptionsMenu(); // This is only necessary for changing an ActionBar
handler.postDelayed(reopenMenu, 100);
}
(Notice I removed the calls to close and open the menu.)
Lastly you should set refresh = false; in onPrepareOptionsMenu() since you only need to make the change once.

It might be easier to have the second button already on the menu but visibility set to GONE, and then make it visible when you need.
MenuItem = menu.findItem(R.id.menuItem);
MenuItem.setVisible(false);

Related

How dynamically add contents to menu item? [duplicate]

I'm trying to change the title of a menu item from outside of the onOptionsItemSelected(MenuItem item) method.
I already do the following;
public boolean onOptionsItemSelected(MenuItem item) {
try {
switch(item.getItemId()) {
case R.id.bedSwitch:
if(item.getTitle().equals("Set to 'In bed'")) {
item.setTitle("Set to 'Out of bed'");
inBed = false;
} else {
item.setTitle("Set to 'In bed'");
inBed = true;
}
break;
}
} catch(Exception e) {
Log.i("Sleep Recorder", e.toString());
}
return true;
}
however I'd like to be able to modify the title of a particular menu item outside of this method.
I would suggest keeping a reference within the activity to the Menu object you receive in onCreateOptionsMenu and then using that to retrieve the MenuItem that requires the change as and when you need it. For example, you could do something along the lines of the following:
public class YourActivity extends Activity {
private Menu menu;
private String inBedMenuTitle = "Set to 'In bed'";
private String outOfBedMenuTitle = "Set to 'Out of bed'";
private boolean inBed = false;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
// Create your menu...
this.menu = menu;
return true;
}
private void updateMenuTitles() {
MenuItem bedMenuItem = menu.findItem(R.id.bedSwitch);
if (inBed) {
bedMenuItem.setTitle(outOfBedMenuTitle);
} else {
bedMenuItem.setTitle(inBedMenuTitle);
}
}
}
Alternatively, you can override onPrepareOptionsMenu to update the menu items each time the menu is displayed.
As JxDarkAngel suggested, calling this from anywhere in your Activity,
invalidateOptionsMenu();
and then overriding:
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem item = menu.findItem(R.id.bedSwitch);
if (item.getTitle().equals("Set to 'In bed'")) {
item.setTitle("Set to 'Out of bed'");
inBed = false;
} else {
item.setTitle("Set to 'In bed'");
inBed = true;
}
return super.onPrepareOptionsMenu(menu);
}
is a much better choice. I used the answer from https://stackoverflow.com/a/17496503/568197
you can do this create a global "Menu" object then assign it in onCreateOptionMenu
public class ExampleActivity extends AppCompatActivity
Menu menu;
then assign here
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
this.menu = menu;
return true;
}
Then later use assigned Menu object to get required items
menu.findItem(R.id.bedSwitch).setTitle("Your Text");
Create a setOptionsTitle() method and set a field in your class. Such as:
String bedStatus = "Set to 'Out of Bed'";
...
public void setOptionsTitle(String status)
{
bedStatus = status;
}
Now when the menu gets populated, change the title to whatever your status is:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(bedStatus);
// Return true so that the menu gets displayed.
return true;
}
You better use the override onPrepareOptionsMenu
menu.Clear ();
if (TabActual == TabSelec.Anuncio)
{
menu.Add(10, 11, 0, "Crear anuncio");
menu.Add(10, 12, 1, "Modificar anuncio");
menu.Add(10, 13, 2, "Eliminar anuncio");
menu.Add(10, 14, 3, "Actualizar");
}
if (TabActual == TabSelec.Fotos)
{
menu.Add(20, 21, 0, "Subir foto");
menu.Add(20, 22, 1, "Actualizar");
}
if (TabActual == TabSelec.Comentarios)
{
menu.Add(30, 31, 0, "Actualizar");
}
Here an example
I use this code to costum my bottom navigation item
BottomNavigationView navigation = this.findViewById(R.id.my_bottom_navigation);
Menu menu = navigation.getMenu();
menu.findItem(R.id.nav_wall_see).setTitle("Hello");
Declare your menu field.
private Menu menu;
Following is onCreateOptionsMenu() method
public boolean onCreateOptionsMenu(Menu menu) {
this.menu = menu;
try {
getMenuInflater().inflate(R.menu.menu_main,menu);
} catch (Exception e) {
e.printStackTrace();
Log.i(TAG, "onCreateOptionsMenu: error: "+e.getMessage());
}
return super.onCreateOptionsMenu(menu);
}
Following will be your name setter activity. Either through a button click or through conditional code
public void setMenuName(){
menu.findItem(R.id.menuItemId).setTitle(/*Set your desired menu title here*/);
}
This worked for me.
You can do it like this, and no need to dedicate variable:
Toolbar toolbar = findViewById(R.id.toolbar);
Menu menu = toolbar.getMenu();
MenuItem menuItem = menu.findItem(R.id.some_action);
menuItem.setTitle("New title");
Or a little simplified:
MenuItem menuItem = ((Toolbar)findViewById(R.id.toolbar)).getMenu().findItem(R.id.some_action);
menuItem.setTitle("New title");
It works only - after the menu created.
You can Change Menu Item text using below Code: -
fun showPopup(v: View) {
popup = PopupMenu(context, v)
val inflater = popup?.menuInflater
popup?.setOnMenuItemClickListener(this)
inflater?.inflate(R.menu.menu_main, popup?.menu)
val menu: Menu = popup!!.menu
val item = menu.findItem(R.id.name)
if (item.title.equals("Name")) {
item.title = "Safal Bhatia"
}
}
It seems to me that you want to change the contents of menu inside a local method, and this method is called at any time, whenever an event is occurred, or in the activity UI thread.
Why don't you take the instance of Menu in the global variable in onPrepareOptionsMenu when this is overridden and use in this method of yours. Be sure that this method is called whenever an event is occurred (like button click), or in the activity UI thread, handler or async-task post-execute.
You should know in advance the index of this menu item you want to change. After clearing the menu, you need to inflate the menu XML and update your item's name or icon.
For people that need the title set statically.
This can be done in the AndroidManifest.xml
<activity
android:name=".ActivityName"
android:label="Title Text" >
</activity>
I needed to change the menu icon for the fragment. I altered Charles’s answer to this question a bit for the fragment:
private Menu top_menu;
//...
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
//...
rootview = inflater.inflate(R.layout.first_content,null);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_menu, menu);
this.top_menu = menu;
}
// my procedure
private void updateIconMenu() {
if(top_menu!= null) {
MenuItem nav_undo = top_menu.findItem(R.id.action_undo);
nav_undo.setIcon( R.drawable.back);
}
}
I hit this problem too. In my case I wanted to set the string to
reflect additional information using getString.
As stated above you need to find the correct menuItem in the menu and set it in the onPrepareOptionsMenu method. The solutions above didn't handle the case where the item was in a sub menu and for this you need to search the submenu for the item. I wrote a little Kotlin recursive function to allow me to this for multiple items. Code below...
override fun onPrepareOptionsMenu(menu: Menu) {
...
menu.menuSetText(R.id.add_new_card,
getString(R.string.add_card, currentDeck.deckName))
...
}
private fun Menu.getMenuItem(idx: Int, itemId: Int): MenuItem? {
Log.d(TAG, "getMenuItem: $idx of ${this.size()}")
if (idx >= size()) return null
val item = getItem(idx)
if (item.hasSubMenu()) {
val mi = item.subMenu.getMenuItem(0, itemId)
// mi non-null means we found item.
if (mi != null)
return mi
}
if (item != null && item.itemId == itemId)
return item
return getMenuItem(idx + 1, itemId)
}
fun Menu.menuSetText(itemId: Int, title: String) {
val menuItem = getMenuItem(0, itemId)
if (menuItem != null)
menuItem.title = title
else
Log.e(TAG,
"menuSetText to \"$title\": Failed to find ${
"itemId:0x%08x".format(itemId)}"
)
}

Change attributes of items on an Android Actionbar

I have an Actionbar displayed on my maps fragment to which I have added a zoom-in button. When selected I would like to replace it with a zoom-out button.
When zoom-in is selected the it is obviously pases in to onOptionsItemSelected as the menu item, so it is easy to set it's attributes like this: viewZoomIn.setVisibility(viewZoomIn.GONE); My problem is, how do I get a reference to the zoom-out button on the action bar to set it as as I would like to viewZoomOut.setVisibility(viewZoomOut.VISIBLE);?
I thought I may be able to store the zoom-in and zoom-out views as instance variables and capture them when I inflate the Actionbar, like this:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
viewZoomIn = findViewById(R.id.zoom_in);
viewZoomOut = findViewById(R.id.zoom_out);
return super.onCreateOptionsMenu(menu);
This does not work.
Any help on getting hold of thes buttons, or advice on a better way of toggling my zoom-in/zoom-out buttons would be appreciated.
It probably shows, but I am pretty new to Java, so it would be preferable is any assistance were communicated in a simple manner.
Thank you.
You have to apply your visibility logic in onPrepareOptionsMenu(Menu) not in onCreateOptionsMenu(Menu) if you want to toggle MenuItem state.
private boolean currentlyZoomedIn;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
// called the first time and after each "invalidateOptionsMenu()"
// if tha Activity is in the "zoomedIn" state, the zoomOut button will be visible
menu.findItem(R.id.zoom_in).setVisible(!currentlyZoomedIn);
menu.findItem(R.id.zoom_out).setVisible(currentlyZoomedIn);
return super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.zoom_in:
// do your logic when zoom_in is clicked
currentlyZoomedIn = true;
break;
case R.id.zoom_out:
// do your logic when zoom_out is clicked
currentlyZoomedIn = false;
break;
}
// force the redraw of the menu
invalidateOptionsMenu();
return super.onOptionsItemSelected(item);
}
By the way, I suggest you to use only one button and move your logic only in onOptionsItemSelected(MenuItem) to avoid an instance variable and the call to invalidateOptionsMenu() in a way like this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// zoom_out_in_id is the id for the common button
if (item.getItemId() == R.id.zoom_out_in_id) {
// get the curren title
final CharSequence title = item.getTitle();
// if the current title is the one of zoom_in button, you have to change its infos to zoom_out ones
if (title.equals("zoom_in_title")) {
// do your logic when zoom_in is clicked
item.setIcon(R.drawable.zoom_out_icon);
item.setTitle("zoom_out_title");
} else if (title.equals("zoom_out_title")) {
// do your logic when zoom_out is clicked
item.setIcon(R.drawable.zoom_in_icon);
item.setTitle("zoom_in_title");
}
}
return super.onOptionsItemSelected(item);
}

Trying to hide a menuitem in Android, not behaving as expected

I have the below menu item created and is showing always as an action, instead of being hidden in an overflow menu.
<item android:id="#+id/menu_refresh_network"
android:orderInCategory="100"
android:icon="#drawable/ic_menu_action_refresh_network"
android:title="#string/title_refresh_network"
android:enabled="true"
app:showAsAction="always" />
I need it to be hidden when ThreshVoteIntentService.mOpportunistic is TRUE. I have a receiver which is alerted by intent when that value has changed. It's a very simple procedure that invalidates the menu.
IntentFilter filterModeUpdated = new IntentFilter(resources.getString(R.string.action_mode_updated));
mModeUpdatedReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
invalidateOptionsMenu();
}
};
this.registerReceiver(mModeUpdatedReceiver, filterModeUpdated);
I have my options menu then (supposedly) redraw in onPrepareOptionsMenu.
#Override
public boolean onPrepareOptionsMenu (Menu menu) {
menu.findItem(R.id.menu_refresh_network).setVisible(ThreshVoteIntentService.mOpportunistic);
return super.onPrepareOptionsMenu(menu);
}
What actually happens is that the visibility of menu_refresh_network only changes when I open the overflow menu. Have I basically misunderstood how this should work?
onPrepareOptionsMenu() is only called, as you say, just before the overflow menu is show, so that's too late.
You need to call setVisible(false) on the correct MenuItem before invalidating the options menu. So in your onCreateOptionsMenu(), find a reference to the MenuItem with findItem() for the item id that you want to change and store that in a member variable. Then, when the broadcast arrives, change the visibility of that item and then invalidate the options menu.
Here is a sample activity based off a new project I created in Android Studio to demonstrate this. If you run this, you can see that the menu item disappears after 5 seconds, and no invalidate is even required to force the menu to refresh.
public class MainActivity extends AppCompatActivity {
private MenuItem menuItem;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Hide the menu item in 5 seconds
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
menuItem.setVisible(false);
}
}, 5000);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
menuItem = menu.findItem(R.id.action_settings);
MenuItemCompat.setShowAsAction(menuItem, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
return true;
}
}
If you are using AppCompatActivity (as app:showAsAction implies), you should use supportInvalidateOptionsMenu() in place of invalidateOptionsMenu() as invalidateOptionsMenu() does not know about always visible action items (hence, why it only calls onPrepareOptionsMenu() when the menu is opened)

android: Update the ActionBar items depending on each Fragment in a ViewPager?

I have a flag/bookmark button in the Action Bar that I want to be toggled on or off depending which Fragment is in view of the ViewPager.
If the user flags a fragment in the ViewPager, it will be set to enabled. When the user swipes to the next one, I want the action bar button to update to unflagged. Now, I'm able to change the state of the button by having two menu items and hide one, show one when clicked.
Here's the code in my Activity to toggle the Action Bar button:
public boolean onOptionsItemSelected(MenuItem item) {
int currentItem = mPager.getCurrentItem();
switch (item.getItemId()) {
case R.id.menu_flag:
mFlagged = true;
supportInvalidateOptionsMenu();
return true;
case R.id.menu_unflag:
mFlagged = false;
supportInvalidateOptionsMenu();
return true;
}
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem item_flag = menu.findItem(R.id.menu_flag);
MenuItem item_unflag = menu.findItem(R.id.menu_unflag);
if (mFlagged) {
//If flagged
//Show flagged item
item_flag.setVisible(false).setEnabled(false);
item_unflag.setVisible(true).setEnabled(true);
item_flag.isVisible();
} else {
//If not flagged
//Show unflagged icon
item_flag.setVisible(true).setEnabled(true);
item_unflag.setVisible(false).setEnabled(false);
}
return super.onPrepareOptionsMenu(menu);
}
The problem I'm having is that I can't access the menu item, save & restore the state of the button, i.e. if it's flagged or not from the fragment or the FragmentPagerAdapter.
How can I do this? Which level should I be accessing the Action Bar; Activity, PagerAdapter or the Fragments?
Registering a ViewPager.OnPageChangeListener on your ViewPager should do the trick. Then, override onPageSelected(int pageNum) to receive callbacks when a page changes.
public void onPageSelected(int pageNum) {
supportInvalidateOptionsMenu();
}

Can I change the Icon on an Actionbar Item

I'm not trying to change the main Icon , just a menu item's icon.
The Icon is essentially displays whether I am recording at that moment. I change the icon when it's tapped using
item.setIcon(R.drawable.recordstart);
In this method.
public boolean onOptionsItemSelected(MenuItem item) {
...
} else if (item.getItemId() == R.id.ab_menu_VRecord) {
if(recording)
{
item.setIcon(R.drawable.recordstop);
}else{
item.setIcon(R.drawable.recordstart);
}
}
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
Anyone know how I can do this outside this method.
Example:
class {
public MenuItem example;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.actionbar, menu);
example = menu.findItem(R.id.ab_menu_exampleview);
return true;
}
}
Then throughout your class you can use
example.setIcon("Your Image");
Not 100% sure where you are wanting to change the icon, but you can certainly cache or create a class member variable and point it at the the MenuItem in your Activity or Fragment for example. After they click it or you inflate it, assign it to the member variable and when you need to change it, you've got a reference or "cached" pointer to it to change the icon.
I think that is a UI change so you might have to be sure that you only call that on the UI thread.
if(!item.isChecked()){
item.setChecked(true);
item.setIcon(R.drawable.icon1);
}else{
item.setChecked(false);
item.setIcon(R.drawable.icon2);
}
is this?

Categories

Resources