Как/где в коде определить, видны ли в ListFragment ListView все элементы?

Я пытаюсь изменить действие ActionBar в зависимости от того, видны ли все элементы списка (на экране меньше элементов, которые помещаются на экран => показать действие «Добавить элемент» | есть некоторые невидимые элементы => показать действие «Поиск»)

Какой метод ListFragment я должен переопределить, чтобы иметь возможность использовать getListView().getLastVisiblePosition() и получить не -1?

Это код из моего ListFragment, но в onCreateOptionsMenu lv.getLastVisiblePosition() всегда возвращает -1.

@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);
    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);
    }
    // ...
}

person Gavriel    schedule 17.03.2016    source источник
comment
попробуйте Looper.myQueue().addIdleHandler и позвоните getLastVisiblePosition внутри IdleHandler   -  person pskink    schedule 17.03.2016
comment
@pskink, я пытался добавить его в onActivityCreated, и он работает, НО: если я возвращаю true, он вызывается все время снова и снова, даже когда ничего не изменилось или не переместилось, и если я верну false, он сработает только один раз   -  person Gavriel    schedule 17.03.2016
comment
Вы хотите, чтобы это было вызвано один раз, не так ли? если нет, возвращайте «false» и addIdleHandler каждый раз при изменении размера вашего адаптера.   -  person pskink    schedule 17.03.2016
comment
@pskink, который сработал, я добавил его в свой адаптер notifyDataSetChanged. Если вы добавите это как ответ, я приму это   -  person Gavriel    schedule 17.03.2016


Ответы (2)


getLastVisiblePosition возвращает действительную позицию только тогда, когда элементы адаптера были добавлены и выложены шлангом ListView, я не знаю никакого способа спросить ListView, когда это произойдет, поэтому лучшим вариантом было бы просто слушать, когда поток пользовательского интерфейса переходит в ожидание блока для большего количества сообщений:

Looper.myQueue().addIdleHandler

и позвоните getLastVisiblePosition() внутри IdleHandler#queueIdle()

person pskink    schedule 17.03.2016
comment
stackoverflow.com/questions/11173369/ также может быть полезно - person Gavriel; 17.03.2016

Чтобы получить видимое количество детей в ListView.

int visibleChildCount = (listView.getLastVisiblePosition() - listView.getFirstVisiblePosition()) + 1;

Теперь получите общее количество детей в ListView,

int totalChildCount = listView.getAdapter().getCount;

Скрыть / показать значок панели действий.

if(totalChildCount>visibleChildCount){
  // Visible
}else{
  // Gone
} 

Надеюсь, что это поможет вам.

person Hiren Patel    schedule 17.03.2016
comment
нет, к сожалению, я это уже знаю, и это даже в коде моего вопроса. Моя проблема заключается в том, какой метод ListFragment я мог бы переопределить, чтобы получить реальные результаты в getLastVisiblePosition(), потому что везде, где я пытался (кроме щелчка элементов списка, просто для проверки правильности расчета) я получаю -1, потому что список еще не заполнен - person Gavriel; 17.03.2016