【问题标题】:Retaining position in ListView after calling notifyDataSetChanged调用 notifyDataSetChanged 后在 ListView 中保留位置
【发布时间】:2011-11-26 03:50:17
【问题描述】:

当用户滚动到底部时,我正在使用 OnScrollListener 将项目动态添加到 ListView。在我将数据添加到适配器并调用 notifyDataSetChanged 之后,ListView 回到顶部。理想情况下,我想保留 ListView 中的位置。关于我应该如何去做这件事有什么想法吗?

【问题讨论】:

  • 嗨,你能分享一下你是如何在 OnScrollListener 中保留和使用列表视图的当前状态的……我也在做同样的事情,但是我从异步任务更新列表……不是工作方式
  • 使用@KamranAhmed 的答案。简单而优雅的解决方案。事实上甚至是正确的

标签: android listview


【解决方案1】:

这就是你想要的吗?

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

// notify dataset changed or re-assign adapter here

// restore the position of listview
mList.setSelectionFromTop(index, top);

2017 年 9 月 28 日编辑:

自 2015 年以来,API 发生了很大变化。类似,但现在是:

// save index and top position
int index = mList.FirstVisiblePosition; //This changed
View v = mList.getChildAt(0);
int top = (v == null) ? 0 : v.Top; //this changed

// notify dataset changed or re-assign adapter here

// restore the position of listview
mList.setSelectionFromTop(index, top);

【讨论】:

  • 谢谢。如果您想将项目添加到列表顶部而不看到更新发生,您需要将添加到索引 int 的项目数添加。 int index = mList.getFirstVisiblePosition() + NUMBER_OF_ADDED_ITEMS;
  • 如果 setSelection 在调用 notifyDataSetChanged 后不能立即工作,这里有一个解决方法:getListView().postDelayed(new Runnable() { @Override public void run() { getListView().setSelection(8) ; } }, 500);据说分配了 Android 错误,所以这应该在某个时候修复:code.google.com/p/android/issues/detail?id=6741
  • 完美运行。此外,如果它可以帮助其他人,这对我来说一开始并不奏效。直到我意识到我以前的无限智慧,我已经添加了lv.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL)。不要那样做......它会强制滚动到列表视图的底部,直到你拉出大部分头发。哈哈。
  • 我使用 getScrollX() 和 setScrollX() 而不是 getFirstVisiblePosition() 和 setSelectionFromTop(),因为在添加内容时仍然会导致一些小的跳跃。
  • 我使用了(非延迟的)post 方法让它工作,不幸的是,它在更新过程中仍然闪烁。
【解决方案2】:

情况:

当您为列表视图设置适配器时,它会刷新其状态。所以,通常会自动向上滚动。

解决办法:

如果没有任何适配器,则将其分配给列表视图,否则仅更新已分配适配器的数据集,而不是将其重新设置为您的列表视图。

下面的链接有详细的教程讲解;

Android ListView: Maintain your scroll position when you refresh

祝你好运!

【讨论】:

  • 这在某种程度上起作用,因为如果我添加一个额外的项目,滚动位置不会移动,但视图中的列表会向下跳以容纳新项目。
  • 这是正确的解决方案,不需要“黑客”来获得如此简单的东西。
【解决方案3】:

我实现了 postDelayed 并且刷新时闪烁。我又搜索了一些,发现我做错了。基本上,每次我想更改数据时,我都不应该创建一个新的适配器。我最终以这种方式完成了它并且它有效:

//goes into your adapter
public void repopulateData(String[] objects) {
    this.objects = null;
    this.objects = objects;
    notifyDataSetChanged();
}

//goes into your activity or list
if (adapter == null) {
    adapter = new Adapter();
} else {
    adapter.repopulateData((String[])data);
}

希望这会有所帮助。

【讨论】:

    【解决方案4】:

    我正在使用

    listView.getFirstVisiblePosition

    保持最后可见的位置。

    【讨论】:

      【解决方案5】:

      使用列表视图的转录模式。

      【讨论】:

        【解决方案6】:

        试试这个

              boolean first=true; 
              protected void onPostExecute(Void result) 
              {
        
              if (first == true) {
              listview.setAdapter(customAdapter);
              first=false;
              }
              else
              customAdapter.notifyDataSetChanged();
              }
        

        【讨论】:

          【解决方案7】:

          代码如下:

          // Save the ListView state (= includes scroll position) as a Parceble
          Parcelable state = listView.onSaveInstanceState();
          
          // e.g. set new items
          listView.setAdapter(adapter);
          
          // Restore previous state (including selected item index and scroll position)
          listView.onRestoreInstanceState(state);  
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2016-04-02
            • 2017-08-30
            • 1970-01-01
            • 1970-01-01
            • 2013-01-08
            • 2017-03-06
            • 2014-10-19
            相关资源
            最近更新 更多