Подтвердить что ты не робот

Есть ли способ предотвратить пересканирование списка в верхнее положение при изменении данных адаптера?

У меня возникли проблемы с сохранением позиции прокрутки списка при изменении данных адаптера.

В настоящее время я создаю пользовательский ArrayAdapter (с переопределенным методом getView) в onCreate в списке ListFragment и затем назначаю его в свой список:

mListAdapter = new CustomListAdapter(getActivity());
mListAdapter.setNotifyOnChange(false);
setListAdapter(mListAdapter);

Затем, когда я получаю новые данные от загрузчика, который периодически выбирает все, я делаю это в своем обратном вызове onLoadFinished:

mListAdapter.clear();
mListAdapter.addAll(data.items);
mListAdapter.notifyDataSetChanged();

Проблема заключается в том, что вызов clear() сбрасывает позицию прокрутки списка. Удаление этого вызова сохраняет позицию, но оно явно оставляет старые элементы в списке.

Каков правильный способ сделать это?

4b9b3361

Ответ 1

Как вы сами указали, вызов функции clear() приводит к тому, что позиция будет reset вверху.

Скрутка с прокруткой и т.д. - это немного взломать, чтобы заставить это работать.

Если ваш CustomListAdapter подклассы из ArrayAdapter, это может быть проблемой:

Вызов clear(), вызывает 'notifyDataSetChanged()'. Вы можете предотвратить это:

mListAdapter.setNotifyOnChange(false); // Prevents 'clear()' from clearing/resetting the listview
mListAdapter.clear();
mListAdapter.addAll(data.items);
// note that a call to notifyDataSetChanged() implicitly sets the setNotifyOnChange back to 'true'!
// That why the call 'setNotifyOnChange(false) should be called first every time (see call before 'clear()').
mListAdapter.notifyDataSetChanged(); 

Я не пробовал это сам, но попробую:)

Ответ 2

Отъезд: Сохранить/Сохранить/Восстановить позицию прокрутки при возврате в ListView

Используйте это, чтобы сохранить позицию в ListView перед вызовом .clear(),.addAll() и. notifyDataSetChanged().

int index = mList.getFirstVisiblePosition();
View v = mList.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();

После обновления адаптера ListView элементы списка будут изменены, а затем установите новую позицию:

mList.setSelectionFromTop(index, top);

В принципе вы можете сохранить свое положение и вернуться к нему, сохранить состояние ListView или все состояние приложения.

Другие полезные ссылки:

Сохранить позицию: Как сохранить и восстановить позицию ListView в Android

Сохранить состояние: Android ListView y позиция

Привет,

Пожалуйста, дайте мне знать, если это поможет!

Ответ 3

Недавно я столкнулся с еще одним вариантом использования (Android 8.1), вызванным ошибкой в коде Android. Если я использую колесико мыши для прокрутки списка - последовательный adapter.notifyDataSetChanged() сбрасывает позицию прокрутки в ноль. Используйте этот обходной путь, пока ошибка не будет исправлена в Android

        listView.onTouchModeChanged(true); // workaround
        adapter.notifyDataSetChanged();

Более подробная информация здесь: https://issuetracker.google.com/u/1/issues/130103876

Ответ 4

В вашем адаптере Expandable/List Adapter поместите этот метод

public void refresh(List<MyDataClass> dataList) {
    mDataList.clear();
    mDataList.addAll(events);
    notifyDataSetChanged();
}

И из вашей деятельности, где вы хотите обновить список, поместите этот код

if (mDataListView.getAdapter() == null) {
    MyDataAdapter myDataAdapter = new MyDataAdapter(mContext, dataList);
    mDataListView.setAdapter(myDataAdapter);
} else {
    ((MyDataAdapter)mDataListView.getAdapter()).refresh(dataList);
}

В случае Расширяемого представления списка вы будете использовать mDataListView.getExpandableListAdapter() вместо mDataListView.getAdapter()