2

I am working on this simple Android application. I have three Menu Items on the Action Bar and each of the menu items inflate 3 different fragments when clicked on them.

My Question: When I click on one of the Menu Items, I want that Menu Item's icon changing to another icon in the drawables folder and STAY like that until I click on another Menu Item and then it will change to the first icon before I clicked on it.

I tried to use a selector .xml with "state_pressed" and when I click on the Menu Item it changes the icon for a second but then it goes back to the first icon as soon as I stop clicking. You can find the related codes below. I'd appreciate it if you could help me with this one.

submenu.xml (Action Bar Menu):

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" >
    <item
        android:id="@+id/action_todo"
        android:title=""
        android:icon="@drawable/action_bar_selector"
        app:showAsAction="always" />
</menu>

action_bar_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:drawable="@drawable/ic_check_box_white_24dp"
        android:state_pressed="true" />
    <item
        android:drawable="@drawable/ic_check_box_white_24dp_unpressed" />
</selector>

ProjectTodo.java (Inflating Action Bar in Fragment Class):

public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
    inflater.inflate(R.menu.submenu, menu);
}

public boolean onOptionsItemSelected(MenuItem item){
    int id = item.getItemId();
    if(id == R.id.action_back){
        ProjectDetails frag = new ProjectDetails();
        ProjectMainListFragmentChanger fragInterface = (ProjectMainListFragmentChanger) getActivity();
        fragInterface.projectMainListChangeFragment(frag);
        return false;
    }

    if(id == R.id.action_details){
        return true;
    }

    if(id == R.id.action_todo){
        ProjectDetails frag = new ProjectDetails();
        ProjectTodoFragmentChanger fragInterface = (ProjectTodoFragmentChanger) getActivity();
        fragInterface.projectTodoChangeFragment(frag);      
        return false;
    }
    return super.onOptionsItemSelected(item);
}

You can see a quick .gif image of the current application. When I click on the Menu Item, it only changes to the 2nd icon for a second and then goes back to its original icon:

enter image description here

Nick Cardoso
  • 20,807
  • 14
  • 73
  • 124
barutto
  • 104
  • 1
  • 14
  • 1
    Action bar is created once per activity. You need to invalidate the action bar whenever you need to change something in action bar. So whenever you click on the icon, reinflate your menu items as well as invalidate the action bar – Balakrishna Avulapati Feb 18 '17 at 19:31

2 Answers2

4

If you just want to toggle the item you can do so using onOptionsItemSelected and onPrepareOptionsMenu

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    boolean result = true;
    switch (item.getItemId()) {
        case R.id.menu_details_save_toggle:
            if (mIsSaved) { //you could modify this to check the icon/text of the menu item
                mIsSaved = false;
            } else {
                mIsSaved = true;
            }
            invalidateOptionsMenu(); //cause a redraw
            break;
        default:
            result = super.onOptionsItemSelected(item);

    }
    return result;
}

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    if (mIsSaved) {
        //in production you'd probably be better off keeping a reference to the item 
        menu.findItem(R.id.menu_details_save_toggle)
            .setIcon(R.drawable.action_saved_on)
            .setTitle(R.string.action_unsave);
    } else {
        menu.findItem(R.id.menu_details_save_toggle)
            .setIcon(R.drawable.action_saved_off)
            .setTitle(R.string.action_save);
    }
    return super.onPrepareOptionsMenu(menu);
}
Nick Cardoso
  • 20,807
  • 14
  • 73
  • 124
  • Thank you for the reply Nick. So I can't achieve what I want simply with selectors xml without using onPrepareOptionsMenu() method yeah? – barutto Feb 18 '17 at 19:40
  • 1
    I don't think it's possible no. But you could work with the checkable interface [See this answer](http://stackoverflow.com/a/31401146/984830) – Nick Cardoso Feb 18 '17 at 19:46
  • 1
    Really a cleverer solution, Finding for hours, +1 ! – Noor Hossain Jul 08 '22 at 00:55
-2

As Simple as it goes !!

ToobarActivity.class:

    public class ToolbarActivity extends AppCompatActivity {

    private Menu menu;// Global Menu Declaration

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_toolbar);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

        setSupportActionBar(toolbar);


        //This is my Back Button View onClick on toolbar
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        this.menu = menu;
        getMenuInflater().inflate(R.menu.main_menu, menu);


        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //This is the Answer to your problem
        if (id == R.id.actionsignout) {
            menu.getItem(1).setVisible(true);
            menu.getItem(0).setVisible(false);
            return true;
        }else if (id == R.id.action) {
            menu.getItem(0).setVisible(true);
            menu.getItem(1).setVisible(false);
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {



        return super.onPrepareOptionsMenu(menu);
    }
}

On res/menu/main_menu.xml:

Set the second item Visibility to false

<?xml version="1.0" encoding="utf-8"?>

<item android:id="@+id/actionsignout"
    app:showAsAction="always"
    android:icon="@drawable/ic_pause_black_24dp"
    android:title="Sign Out"/>

<item android:id="@+id/action"
    app:showAsAction="ifRoom"
    android:visible="false" 
    android:icon="@drawable/ic_play_arrow_black_24dp"
    android:title=""/>

  • While this code may answer the question, providing information on how and why it solves the problem improves its long-term value – L_J Jul 15 '18 at 15:55