web-dev-qa-db-ja.com

ActionBarメニュー項目アイコンを動的に変更する方法

サーバーからの通知を受け取りながら、メニュー項目のアイコンを動的に変更したい。ただし、メニュー項目のアイコンを変更するコードを実行すると、NullPointerExceptionが表示されます。

メニュー項目のアイコンを変更するために使用したコードは、onCreatOptionsMenuメソッドで次のように定義されています。

 @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);
     }
 }

updateCountメソッドでは、次のようにアイコンを変更しています。

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);
                        }
                    }
                }
            }                   
        }
    });
}

これが私のmenuitem「通知」ファイルです:

<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>

これが私の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)

助けてください。

10
ankur arora

メニューが膨らんでいない(menu.getItem(index)をチェックしている)か、存在しないindexがある可能性があるため、mDrawerLayout != null && isDrawerOpen()がnullを返しているようです。メニュー項目のインデックスに依存する代わりに、リソースIDを使用できます。また、nullをチェックしてください。

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

更新:あなたのコードに基づいて、私は以下の例を実行しました。ベースとして、またはコードが機能しない理由を見つけるために比較するために使用できます。 @layout/action_bar_notification_iconがどのように見えるかわかりませんので、あなたの場合は問題があるかもしれません。

この例では、メニュー項目をクリックすると、ic_menu_deleteがic_menu_editに置き換えられます。

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>

コード:

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()は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
Dario

私も同じ問題を抱えており、invalidateOptionsMenu()を呼び出さない限り、@ Darioの回答は魅力のように機能します。

これを解決するために、ドローアブルリソースを変数に割り当て、アイコンを変更するinvalidateOptionsMenu()を呼び出し、onCreateOptionsMenu()でアイコンを設定します。コードは次のようになります。

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);
}
4
Zinc

3つのステップがあります:

  1. グローバルMenuItem変数を定義します。
  2. onCreateOptionsMenuメソッドで、値(ターゲットメニュー)を割り当てます。
  3. 必要に応じてアイコンを変更します。

     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);
       }
       //...
    }
    
0
sepehr

私も同じ問題を抱えています。メニュー項目に次のものがあることを確認してください(アイコンとshowAsActionが常に設定されている):

Android:icon="@Android:drawable/ic_menu_delete" 
app:showAsAction="always"
0
Ana_Maria