Есть ли способ предотвратить пересканирование списка в верхнее положение при изменении данных адаптера?
У меня возникли проблемы с сохранением позиции прокрутки списка при изменении данных адаптера.
В настоящее время я создаю пользовательский ArrayAdapter (с переопределенным методом getView) в onCreate
в списке ListFragment и затем назначаю его в свой список:
mListAdapter = new CustomListAdapter(getActivity());
mListAdapter.setNotifyOnChange(false);
setListAdapter(mListAdapter);
Затем, когда я получаю новые данные от загрузчика, который периодически выбирает все, я делаю это в своем обратном вызове onLoadFinished
:
mListAdapter.clear();
mListAdapter.addAll(data.items);
mListAdapter.notifyDataSetChanged();
Проблема заключается в том, что вызов clear()
сбрасывает позицию прокрутки списка. Удаление этого вызова сохраняет позицию, но оно явно оставляет старые элементы в списке.
Каков правильный способ сделать это?
Ответы
Ответ 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()