How to change the icon of an ActionBar menu item dynamically

I want to change the menu item icon dynamically when I receive a notification from the server. However, I get a NullPointerException when the codes for changing the menu item icon are executed.

The codes that I used to change the menu item icon are defined in the onCreatOptionsMenu method as follows:

  @Override public boolean onCreateOptionsMenu(Menu menu) { // getMenuInflater().inflate(R.menu.main, menu); this.menu = menu; if (mDrawerLayout != null && isDrawerOpen()) showGlobalContextActionBar(); MenuInflater menuInflater = this.getMenuInflater(); menuInflater.inflate(R.menu.notification, menu); return super.onCreateOptionsMenu(menu); } } 

and in the updateCount method updateCount I change the icon as follows:

 public void updateCount(int count) { hot_count = count; System.out.println("Value of count: " + count); runOnUiThread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub if (hot_count > 0) { if(hot_count>0) { if (menu != null) { MenuItem item = menu.findItem(R.id.menu_hotlist); if (item != null) { item.setIcon(R.drawable.ic_notification1); } } } } } }); } 

Here is my notification file for my menu.

 <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" > <item android:id="@+id/menu_hotlist" android:actionLayout="@layout/action_bar_notification_icon" android:showAsAction="always" android:icon="@drawable/ic_notification" android:title="Notification" /> </menu> 

Here is my logcat:

 01-20 15:03:29.811: E/AndroidRuntime(10318): java.lang.NullPointerException 01-20 15:03:29.811: E/AndroidRuntime(10318): at com.xsinfosol.helpdesk_customer.TAB_Activity$3.run(TAB_Activity.java:294) 01-20 15:03:29.811: E/AndroidRuntime(10318): at android.os.Handler.handleCallback(Handler.java:730) 01-20 15:03:29.811: E/AndroidRuntime(10318): at android.os.Handler.dispatchMessage(Handler.java:92) 01-20 15:03:29.811: E/AndroidRuntime(10318): at android.os.Looper.loop(Looper.java:137) 01-20 15:03:29.811: E/AndroidRuntime(10318): at android.os.HandlerThread.run(HandlerThread.java:61) 01-20 15:04:04.881: I/System.out(11629) 

Please, help.

+8
android android-actionbar menuitem
source share
4 answers

It looks like menu.getItem(index) returns null because the menu was not overestimated (you have the mDrawerLayout != null && isDrawerOpen() check), or you may have an index that does not exist. Instead of relying on the index of the menu item, you can use the resource identifier, also check the null value:

 if (menu != null) { MenuItem item = menu.findItem(R.id.your_menu_action); if (item != null) { item.setIcon(R.drawable.ic_notification1); } } 

Update: based on the code I provided below that works. You can use it as a base or for comparison to find why your code is not working. I don't know what @layout/action_bar_notification_icon looks like, so there might be a problem in your case.

In this example, ic_menu_delet e is replaced with ic_menu_edit after clicking on a menu item.

test_menu.xml

 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/test_menu_item" android:icon="@android:drawable/ic_menu_delete" android:showAsAction="always" android:title="Item1"/> </menu> 

the code:

 private Menu menu; @Override public boolean onCreateOptionsMenu(Menu menu) { this.menu = menu; getMenuInflater().inflate(R.menu.test_menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.test_menu_item: changeIcon(); break; default: break; } return super.onOptionsItemSelected(item); } 

changeIcon () mimics your updateCount ()

 public void changeIcon(){ runOnUiThread(new Runnable() { @Override public void run() { if (menu != null) { MenuItem item = menu.findItem(R.id.test_menu_item); if (item != null) { item.setIcon(android.R.drawable.ic_menu_edit); } } } }); } 
+9
source share

I also had the same issue, and @Dario's answers work like a charm if you don't call invalidateOptionsMenu()

To solve this problem, I assign a resource with a variable to call the variable and call invalidateOptionsMenu() , where I want to change the icon, and I set the icon to onCreateOptionsMenu() . The code should look like this:

 private int drawableResourceId = R.drawable.default_menu_icon; @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.test_menu, menu); menu.findItem(R.id.change_menu_item_icon).setIcon(drawableResourceId); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.change_menu_item_icon: drawableResourceId = R.drawable.changed_menu_icon; invalidateOptionsMenu(); break; default: break; } return super.onOptionsItemSelected(item); } 
+3
source share

I had the same problem. Make sure your menu item has the following (the icon and showAsAction are always set):

 android:icon="@android:drawable/ic_menu_delete" app:showAsAction="always" 
0
source share

There are three steps:

  • define the global variable MenuItem .
  • in onCreateOptionsMenu assign your value (menu target).
  • change icon.

      public class NotificationActivity extends BaseActivity { //#1 Menu globalMenuItem; //other variables @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.notification_menu, menu); //#2 globalMenuItem= menu.add(Menu.NONE,menuId, Menu.NONE, title); globalMenuItem.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS) .setIcon(R.drawable.notification_icon_1); //other menu items } //#3 private void changeIcon(){ flashMenuItem.setIcon(R.drawable.notification_icon_2); } //... } 

    Hope this helps.

0
source share

All Articles