2

I have a Toolbar within my app which I would like to modify it contents dynamically, during the app execution (in other words, on run-time).

For example, the app is capable of taking and previewing photos; once that photos are previewed, the user is able to select some photos and perform a sending action to a server. I want also to make the user able to delete photos once that some of them are selected and for doing that I would like that the "delete" item on the action bar (identifiable via the trash icon) will be visible only when one or more photos are selected.

Is this possible to do? If yes, how?

Toolbar

In other words and, more generically, I want to control items (visibility) in the toolbar, setting the code as they will be "visible" only when some conditions are "true" (in the example above, when photos are selected or, in a different example, when user is logged) and invisible when they are "false" (when user isn't logged).

For now I just need to "remove" (or make invisible) items in the Toolbar, but it will be useful also to know if is possible to add items in the toolbar on run-time.

I'm adding some code which can help to understand the problem.

app_bar.xml file in "/res/layout", which graphically defines the Toolbar

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

<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/my_toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:elevation="4dp"
    android:theme="@style/ToolbarTheme" />

menu_resources.xml file, which defines the Toolbar items

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<!-- "User favourite function", should appear as action button if possible -->
<item
    android:id="@+id/action_app_icon"
    android:icon="@mipmap/ic_launcher"
    android:title="@string/action_bar_app_icon"
    app:showAsAction="always" />

<!-- Settings, should always be in the overflow -->
<item
    android:id="@+id/action_delete"
    android:icon="@drawable/trash"
    android:title="@string/action_bar_delete"
    app:showAsAction="always"/>

<!-- Settings, should always be in the overflow -->
<item
    android:id="@+id/action_settings"
    android:icon="@drawable/settings"
    android:title="@string/action_bar_settings"
    app:showAsAction="never"/>

<!-- About, should always be in the overflow -->
<item
    android:id="@+id/about"
    android:icon="@android:drawable/ic_dialog_info"
    app:showAsAction="never"
    android:title="@string/action_bar_about"/>

Part of the activity in which the toolbar is

public class myClass extends AppCompatActivity implements View.OnClickListener {

// Instantiating a toolbar
private Toolbar toolbar;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my_class);

    // Adding toolbar to the activity
    toolbar = (Toolbar) findViewById(R.id.my_toolbar);
    setSupportActionBar(toolbar);

    // Get a support ActionBar corresponding to this toolbar
    ActionBar ab = getSupportActionBar();
    // Enable the Up button
    ab.setDisplayHomeAsUpEnabled(true);
    }

    // The method that creates an options menu
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_resource, menu);
        // This make the delete item invisible
        menu.findItem(R.id.action_delete).setVisible(false);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_settings:
                // Perform the settings action
                return true;
            case R.id.about:
                // Perform the about
                return true;
            case R.id.action_delete:
                deletePhotos();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }


    public static void manageSelection(Boolean state, int position){
        if (photoArray.getNumberSelected() == 0) {
            // disable the trash icon and its functionality;
        } else {
            // enable the trash icon with its functionality;
        }
    }

    // This method allows to deleteItems images to the array
    public void deletePhotos() {
        //code for deleting photos
    }
}

Thanks for your time.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115

2 Answers2

9

Try this code in your activity please:

public class ActivityClass extends AppCompatActivity {

    MenuItem menuItem; // Make global toolbar's menuItem

    .
    .
    .

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_layout, menu);

        menuItem = menu.findItem(R.id.toolbar_action_button) // Your toolbar´s button ID and save it in your global menuItem

        return super.onCreateOptionsMenu(menu);
    }

    public void showMenuItem(){
        menuItem.setVisible(true); // Call this method in runtime when you need show it
    }

    public void hideMenuItem(){
        menuItem.setVisible(false); // Call this method in runtime when you need hide it
    }

[EDIT]

Thanks to Alessandro Iudicone´s comment we have an alternative way to get the toolbar´s menu too without the global MenuItem but only global Toolbar instance:

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

    public void showMenuItem(){
        toolbar.getMenu().findItem(R.id.toolbar_actio‌​n_button).setVisible‌​(true);
    }

    public void hideMenuItem(){
        toolbar.getMenu().findItem(R.id.toolbar_actio‌​n_button).setVisible‌​(false);
    }

Hope it helps :)

Crono
  • 2,024
  • 18
  • 16
  • 2
    I tried your code and it works fine :) In the meantime, I find out that the method "getMenu()" can accomplish this too and in your example could be "public void showMenuItem(){toolbar.getMenu().findItem(R.id.toolbar_action_button).setVisible(true)};" and "public void hideMenuItem(){toolbar.getMenu().findItem(R.id.toolbar_action_button).setVisible(false)};" , with "toolbar" defined as it is in my code. I think that this solution is better because it avoids creating e new field. If you agree with me, can you please add this information as an alternative way in your answer? Thank you :) – Alessandro Iudicone Oct 18 '17 at 15:00
0

For hiding the icon:

toolbar.findViewById(R.id.menu_item_id).setVisibility(View.INVISIBLE);

For adding a view to the toolbar:

TextView textView = new TextView(MainActivity.this);
textView.setText("Hello World");
toolbar.addView(textView);

This only works for views on the toolbar itself, not for the overflow menu. You'll probably have to use code found in this stack overflow answer if you want to mess with the overflow menu: Android Toolbar overflow menu view id

tim.paetz
  • 2,635
  • 20
  • 23
  • I tried with your code and the part for adding a view seems ok...but hiding an icon seems not working because the method "setVisible" is displayed in red in Android Studio and the error "cannot resolve method 'setVisible(int)'" occurs. I'm not sure that you can perform the method 'setVisible' on an item of a toolbar (which, I think, is not a view) . – Alessandro Iudicone Oct 18 '17 at 15:11
  • Sorry, typo. It should have been setVisibility. I updated my answer. – tim.paetz Oct 18 '17 at 15:15
  • I tried your code for hiding the icon and seems to crash. I also debugged and find out that it crashes at that exact line with the error "java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.setVisibility(int)' on a null object reference". Anyway, the part for adding a view works and can be useful. Thank you. – Alessandro Iudicone Oct 18 '17 at 15:35
  • The code works fine if it isn't in the overflow menu. Are you using a menu ID that is in the overflow menu? – tim.paetz Oct 18 '17 at 15:41
  • No, I tried on an item represented by an icon, which is not in the overflow menu. – Alessandro Iudicone Oct 18 '17 at 15:52
  • I tried again today and it seems to work fine, both on TextViews and on Items inside the toolbar (I don't know what I've changed). There is a little problem when you set views as `INVISIBLE` in this way, that is the icon goes invisible but space remains occupied so if there are icons to the left of the one set as invisible, a portion of space remains unused and other icons remain at the left of that space. Maybe there is a way to refresh the Toolbar that I don't know. – Alessandro Iudicone Oct 19 '17 at 07:23
  • Find out that with `toolbar.getMenu().findItem(R.id.menu_item_id).setVisible(false);` that unused space goes away – Alessandro Iudicone Oct 19 '17 at 07:29
  • 1
    You can use View.GONE instead of View.INVISIBLE if you want it gone rather than invisible. – tim.paetz Oct 19 '17 at 15:14