Gavriel
Gavriel

Reputation: 19237

Change actions in ActionBar depending on number of visible items in ListFragment

I am trying to achieve the following user-experience: When I have more items in my ListFragment's adapter that can be displayed on the screen, I would like to show the Search action in the ActionBar, but when there are less, then the Add Item action.

I face 2 problems:

  1. I am trying to calculate in onCreateOptionsMenu wether the the number of items are less or more than what can be displayed on the screen, but in that stage the ListView is always empty. Where should I move that calculation, and how can I set the menu actions from another method?

  2. When I use menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM) in my code, it does have the effect of not displaying it in the ActionBar, but when I click on it in the MenuOverflow, it doesn't act at all.

I use minSdkVersion 15 without compatibility or support library.

res/menu/list.xml:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.fletech.android.opensesame.key.KeyringActivity" >
    <item android:id="@+id/menu_item_add_item"
        android:orderInCategory="100"
        android:showAsAction="always"
        android:icon="@android:drawable/ic_menu_add"
        android:title="Add key" />
    <item android:id="@+id/menu_item_search"
        android:orderInCategory="200"
        android:showAsAction="ifRoom|collapseActionView"
        android:icon="@android:drawable/ic_menu_search"
        android:title="Search"
        android:actionViewClass="com.fletech.android.opensesame.app.CursorFragment$MySearchView"/>

    <!-- I have more menu items here -->

</menu>

And the code:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(R.menu.list, menu);

    final MenuItem search = menu.findItem(R.id.menu_item_search);
    mSearchView = (MySearchView)search.getActionView();
    mSearchView.setOnQueryTextListener(this);
    mSearchView.setOnCloseListener(this);
    mSearchView.setIconifiedByDefault(true);

    final ListView lv = getListView();
    if (lv.getFirstVisiblePosition() == 0 && lv.getLastVisiblePosition() == mAdapter.getCount()-1) {
        // all items visible: show add, hide search
        search.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
    } else {
        // not all items visible: show search, hide add
        final MenuItem add = menu.findItem(R.id.menu_item_add_item);
        add.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
    }
}

update: the second issue was resolved by moving the mSearchView lines to after the setShowAsAction() calls:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(R.menu.list, menu);

    SendInvitationActivity.onCreateShareOptionsMenu(getActivity(), menu, R.id.menu_item_share);

    final MenuItem search = menu.findItem(R.id.menu_item_search);
    final MenuItem add = menu.findItem(R.id.menu_item_add_item);

    final ListView lv = getListView();
    if (lv.getFirstVisiblePosition() == 0 && lv.getLastVisiblePosition() == mAdapter.getCount()-1) {
        // all items visible: show add, hide search
        search.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
    } else {
        // not all items visible: show search, hide add
        add.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
    }

    mSearchView = (MySearchView)search.getActionView();
    mSearchView.setOnQueryTextListener(this);
    mSearchView.setOnCloseListener(this);
    mSearchView.setIconifiedByDefault(true);
}

Upvotes: 1

Views: 85

Answers (1)

Khang .NT
Khang .NT

Reputation: 1579

  1. When the Adapter items changed (added / removed), you need check number of items displayed and then if you want call onCreateOptionsMenu again, just call:

    Activity.invalidateOptionsMenu();
    // Your Adapter
    @Override
    public void notifyDataSetChanged() {
        super.notifyDataSetChanged();
        invalidateOptionsMenu(); // call after super.notifyDataSetChanged();
        // let's delay a second if still problem
        // new Handler().postDelay();
    }
    
  2. Try this:

     final MenuItem add = menu.findItem(R.id.menu_item_add_item);
     final MenuItem search = menu.findItem(R.id.menu_item_search_item);
     int numberItemsVisible = lv.getLastVisiblePosition() - lv.getFirstVisiblePosition() + 1;
     if (numberItemsVisible == mAdapter.getCount()) {
         // all items visible: show add, hide search
         add.setShowAsAction(MenuItem.ALWAYS);
         search.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
         // or search.setShowAsAction(MenuItem.NEVER);
     } else {
         // not all items visible: show search, hide add
         add.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
         // or add.setShowAsAction(MenuItem.NEVER);
         search.setShowAsAction(MenuItem.ALWAYS);
     }
    

Upvotes: 1

Related Questions