Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to call findViewById with menu item id to ensure it is not null?

I'm inflating the menu and trying to find the view of one of the menu items in the following way:

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

     // will print `null`
     Log.i("TAG", String.valueOf(findViewById(R.id.action_hello)));
     return true;
 }

In the result null is printed in Logcat. However if I add some delay before calling findViewById, it returns correct View object:

@Override
public boolean onCreateOptionsMenu(final Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    new AsyncTask<Void, Void, Void>() {
        @Override
        protected Void doInBackground(final Void... voids) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(final Void aVoid) {
            // will print correctly android.support.v7.view.menu.ActionMenuItemView...
            Log.i("TAG", String.valueOf(findViewById(R.id.action_hello)));
        }
    }.execute();
    return true;
}

Of course this solution is very dirty and the minimal delay is unknown. Is there a way to register some callback for the menu inflated event. In other words: how can I call findViewById with the menu item id to be sure that the view is already there and this call won't return null?

like image 306
Piotr Aleksander Chmielowski Avatar asked Jun 12 '18 15:06

Piotr Aleksander Chmielowski


People also ask

What does the function findViewById int id return if the ID isn't found?

. findViewById(R. id. retry) would always return null.

What is findViewById () method used for?

FindViewById<T>(Int32) Finds a view that was identified by the id attribute from the XML layout resource.

What is findViewById R ID?

findViewById is the method that finds the View by the ID it is given. So findViewById(R. id. myName) finds the View with name 'myName'.

What does findViewById return?

findViewById returns an instance of View , which is then cast to the target class. All good so far. To setup the view, findViewById constructs an AttributeSet from the parameters in the associated XML declaration which it passes to the constructor of View . We then cast the View instance to Button .


3 Answers

Just override public void onPrepareOptionsMenu(Menu menu).

Documentation says:

This is called right before the menu is shown, every time it is shown. You can use this method to efficiently enable/disable items or otherwise dynamically modify the contents.

The view for Menu is created after calling onCreateOptionsMenu(Menu), that's why you can't access it subviews.

like image 69
Nominalista Avatar answered Sep 22 '22 01:09

Nominalista


There are two ways to find the menu item view.

Frist way:-

Add a actionViewClass in your menu item, so that you can get view returned by getActionView. As getActionView() only works if there's a actionView defined for menuItem.

Add this in your menu item xml:-

<item
    android:id="@+id/menuAdd"
    android:icon="@android:drawable/ic_menu_add"
    android:title="Add"
    app:showAsAction="always"
    app:actionViewClass="android.widget.ImageButton" />

In onCreateOptionsMenu method:-

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_item,menu);
    View menuView=menu.findItem(R.id.menuAdd).getActionView();
    Log.e("TAG", "onCreate: "+menuView );
    return true;
}

Second way:-

The second way is to use a handler. Using this method you won't need to specify the time for the delay. Check the answer given by @davehenry here

like image 39
Nainal Avatar answered Sep 19 '22 01:09

Nainal


You must call the super method when your code is finished or things just don't work as expected.

@Override
     public boolean onCreateOptionsMenu(final Menu menu) {
         getMenuInflater().inflate(R.menu.main, menu);
    super.onCreationOptionsMenu(menu);
         // calling the super completes the method now you code.
         Log.i("TAG", String.valueOf(findViewById(R.id.action_hello)));
         return true;
     }
like image 21
danny117 Avatar answered Sep 20 '22 01:09

danny117