Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change the ActionBar menu item's icon dynamically

I want to change the menu item's icon dynamically as I get notification from a server. However, I'm getting a NullPointerException when the codes to change the menu item's icon run.

Codes I used to change the menu item's icon are defined in the onCreatOptionsMenu method as follow:

 @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, I am changing the icon as follow:

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 menuitem "notification" file:

<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's 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.

like image 832
ankur arora Avatar asked Jan 20 '15 09:01

ankur arora


People also ask

What are action bar icons?

Android ActionBar is a menu bar that runs across the top of the activity screen in android. Android ActionBar can contain menu items which become visible when the user clicks the “menu” button. In general an ActionBar consists of the following four components: App Icon: App branding logo or icon will be displayed here.

How to add icon in Action Bar Android studio?

To generate ActionBar icons, be sure to use the Asset Studio in Android Studio. To create a new Android icon set, right click on a res/drawable folder and invoke New -> Image Asset.

How to create Action Bar menu in Android?

Right-click on the res folder and selects New -> Directory. Give the name “menu” to the new directory. Further, create a new Menu Resource File by right click on the menu directory. As the ActionBar is being created for the main Activity, type the name as “main” to the Menu Resource File.


2 Answers

Looks like menu.getItem(index) is returning null because menu was not inflated ( you have check mDrawerLayout != null && isDrawerOpen()) or you might have index that doesn't exists. Instead of relying on menu item index you can use resource id, also do check for null:

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

Update: based on you code i did example below that works. You can use it as base or for comparing to find why your code is not working. I don't know how @layout/action_bar_notification_icon looks like so in your case might be problem there.

In this example ic_menu_delete is replaced by ic_menu_edit once you click on 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>

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() simulates 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);
                }
            }
        }
    });
}
like image 188
Dario Avatar answered Oct 24 '22 09:10

Dario


I've also had the same problem and @Dario answers works like a charm as long as you don't call invalidateOptionsMenu()

To solve this, I assign the drawable resource to a variable and call invalidateOptionsMenu() where I want to change the icon and I set the icon in onCreateOptionsMenu(). The code should be 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);
}
like image 6
Zinc Avatar answered Oct 24 '22 10:10

Zinc