Paul C Paul C - 6 months ago 13
Android Question

Change attributes of items on an Android Actionbar

I have an Actionbar displayed on my maps fragment to which I have added a zoom-in button. When selected I would like to replace it with a zoom-out button.

When zoom-in is selected the it is obviously pases in to onOptionsItemSelected as the menu item, so it is easy to set it's attributes like this: viewZoomIn.setVisibility(viewZoomIn.GONE); My problem is, how do I get a reference to the zoom-out button on the action bar to set it as as I would like to viewZoomOut.setVisibility(viewZoomOut.VISIBLE);?

I thought I may be able to store the zoom-in and zoom-out views as instance variables and capture them when I inflate the Actionbar, like this:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
viewZoomIn = findViewById(R.id.zoom_in);
viewZoomOut = findViewById(R.id.zoom_out);
return super.onCreateOptionsMenu(menu);


This does not work.

Any help on getting hold of thes buttons, or advice on a better way of toggling my zoom-in/zoom-out buttons would be appreciated.

It probably shows, but I am pretty new to Java, so it would be preferable is any assistance were communicated in a simple manner.

Thank you.

Answer

You have to apply your visibility logic in onPrepareOptionsMenu(Menu) not in onCreateOptionsMenu(Menu) if you want to toggle MenuItem state.

private boolean currentlyZoomedIn;

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main_menu, menu);
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    // called the first time and after each "invalidateOptionsMenu()"
    // if tha Activity is in the "zoomedIn" state, the zoomOut button will be visible
    menu.findItem(R.id.zoom_in).setVisible(!currentlyZoomedIn);
    menu.findItem(R.id.zoom_out).setVisible(currentlyZoomedIn);
    return super.onPrepareOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()){
        case R.id.zoom_in:
            // do your logic when zoom_in is clicked
            currentlyZoomedIn = true;
            break;
        case R.id.zoom_out:
            // do your logic when zoom_out is clicked
            currentlyZoomedIn = false;
            break;
    }
    // force the redraw of the menu
    invalidateOptionsMenu();
    return super.onOptionsItemSelected(item);
}

By the way, I suggest you to use only one button and move your logic only in onOptionsItemSelected(MenuItem) to avoid an instance variable and the call to invalidateOptionsMenu() in a way like this:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // zoom_out_in_id is the id for the common button
    if (item.getItemId() == R.id.zoom_out_in_id) {
        // get the curren title
        final CharSequence title = item.getTitle();
        // if the current title is the one of zoom_in button, you have to change its infos to zoom_out ones
        if (title.equals("zoom_in_title")) {
            // do your logic when zoom_in is clicked
            item.setIcon(R.drawable.zoom_out_icon);
            item.setTitle("zoom_out_title");
        } else if (title.equals("zoom_out_title")) {
            // do your logic when zoom_out is clicked
            item.setIcon(R.drawable.zoom_in_icon);
            item.setTitle("zoom_in_title");
        }
    }
    return super.onOptionsItemSelected(item);
}