'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.
Solution 1:[1]
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);
}
}
}
});
}
Solution 2:[2]
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);
}
Solution 3:[3]
I've had the same problem. Please make sure you have the following in your menu item (an icon and showAsAction set to always) :
android:icon="@android:drawable/ic_menu_delete"
app:showAsAction="always"
Solution 4:[4]
There are 3 steps:
- define a global
MenuItemvariable . - in
onCreateOptionsMenumethod assign your value (the target menu) to it. change the icon when required.
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 call this when required private void changeIcon(){ globalMenuItem.setIcon(R.drawable.notification_icon_2); } //... }
Solution 5:[5]
As the docs state here, you should use onPrepareOptionsMenu() for any menu changes during the runtime of the Activity. It gets invoked whenever you call invalidateOptionsMenu().
Summary:
- Do the initialization of the menu in
onCreateOptionsMenu() - Whatever needs to be updated dynamically goes in
onPrepareOptionsMenu() - Call
invalidateOptionsMenu()when you have detected a change and want to update the options menu
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Zinc |
| Solution 3 | Ana_Maria |
| Solution 4 | |
| Solution 5 | Leo |
