21

在更改适配器的数据时,我在保留列表视图的滚动位置时遇到了一些麻烦。

我目前正在做的是在onCreateListFragment 中创建一个自定义 ArrayAdapter(具有重写的 getView 方法),然后将其分配给它的列表:

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

然后,当我从定期获取所有内容的加载程序接收到新数据时,我在其onLoadFinished回调中执行此操作:

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

问题是,调用会clear()重置列表视图的滚动位置。删除该调用会保留该位置,但显然会将旧项目留在列表中。

这样做的正确方法是什么?

4

4 回答 4

34

正如您自己指出的那样,对“clear()”的调用会导致位置重置为顶部。

摆弄滚动位置等是让这个工作的一个小技巧。

如果您的 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's why the call 'setNotifyOnChange(false) should be called first every time (see call before 'clear()').
mListAdapter.notifyDataSetChanged(); 

我自己没试过,但试试看:)

于 2013-02-06T00:30:06.057 回答
6

签出:返回 ListView 时保持/保存/恢复滚动位置

在调用 .clear()、.addAll() 和 .之前,使用它来保存 ListView 中的位置。通知数据集更改()。

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

更新 ListView 适配器后,Listview 的项目将被更改,然后设置新的位置:

mList.setSelectionFromTop(index, top);

基本上你可以保存你的位置并滚动回它,保存 ListView 状态或整个应用程序状态。

其他有用的链接:

保存位置: 如何在 Android 中保存和恢复 ListView 位置

保存状态: Android ListView y 位置

问候,

请让我知道这可不可以帮你!

于 2013-02-05T23:13:02.447 回答
0

我最近遇到了另外一个用例(Android 8.1)——由 Android 代码中的错误引起。如果我使用鼠标滚轮滚动列表视图 - 连续adapter.notifyDataSetChanged()将滚动位置重置为零。使用此解决方法,直到错误在 Android 中得到修复

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

更多细节在这里:https ://issuetracker.google.com/u/1/issues/130103876

于 2019-04-07T23:44:55.377 回答
-1

在您的可扩展/列表适配器中,放置此方法

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);
}

如果是Expandable List View,您将使用 mDataListView.getExpandableListAdapter()而不是 mDataListView.getAdapter()

于 2013-09-30T11:51:34.123 回答