使用反向无限滚动添加到 ListView 时保持滚动位置

2024-05-09

我正在构建一个类似聊天的 Android 应用程序,类似于环聊。为此,我使用垂直 ListViewstackFromBottom=true and transcriptMode="normal".

该列表按从较旧的消息(顶部)到较新的消息(底部)排序。在正常状态下,ListView滚动到底部,显示最新的消息。

一旦用户滚动到列表顶部,ListView 使用反向无限滚动适配器来加载更多(较旧)消息。加载较旧的消息后,它们将被添加到列表的顶部。

所需的行为是,当较旧的消息添加到列表顶部时,ListView 将其滚动位置保持在列表底部。也就是说,当较旧的消息添加到顶部时,滚动视图应显示与添加较旧的消息之前显示的相同的消息。

不幸的是,这不起作用。而不是将滚动位置保持在底部,ListView 将滚动位置保持在列表顶部。也就是说,将较旧的消息添加到列表后,列表将显示最上面(即最旧的)消息。

当向顶部添加新项目时,是否有一种简单的方法告诉 ListView 将其滚动位置保持在底部而不是顶部?

Update

出于演示目的,我尽可能地减少了用例和代码。以下示例创建一个简单的字符串数组列表。单击一个项目将在列表顶部添加另一个项目。长按一个项目将在列表底部添加另一个项目。

在列表底部添加项目(长按)时一切正常。当在列表顶部添加项目时(只需单击),则有 3 种情况:

  • 如果列表滚动到底部,则一切正常。将项目添加到顶部后,列表仍然滚动到底部。
  • 如果列表没有滚动到底部(也没有滚动到顶部),则列表将保持其滚动 y 位置(从顶部开始)。这使得列表看起来“跳跃”了一项。在这种情况下,我希望列表不要“跳跃”,即我希望它保持从底部开始的滚动位置。
  • 如果列表滚动到顶部,则会发生与情况 2 相同的情况。首选行为与情况 2 相同。

(最后两种情况实际上是相同的。我将它们分开是因为在情况2中可以更好地演示问题。)

Code

public class MyListActivity extends Activity {
  int topIndex = 1;

  int bottomIndex = 20;

  protected final void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.my_list_activity);

    final ListView list = (ListView) findViewById(R.id.list);
    list.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);
    list.setStackFromBottom(true);

    final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1);
    for (int i = topIndex; i <= bottomIndex; i++) {
      adapter.add(Integer.toString(i));
    }
    list.setAdapter(adapter);

    list.setOnItemClickListener(new OnItemClickListener() {
      @Override
      public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        adapter.insert(Integer.toString(--topIndex), 0);
      }
    });

    list.setOnItemLongClickListener(new OnItemLongClickListener() {
      @Override
      public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        adapter.add(Integer.toString(++bottomIndex));
        return true;
      }
    });
  }
}

我已经想通了。无论您在何处获取新数据,我都会在更改适配器中的数据之前调用以下命令:

int firstVisibleItem = list.getFirstVisiblePosition();
int oldCount = adapter.getCount();
View view = list.getChildAt(0);
int pos = (view == null ? 0 :  view.getBottom());

然后我打电话:

adapter.setData(data);

list.setSelectionFromTop(firstVisibleItem + adapter.getCount() - oldCount + 1, pos);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用反向无限滚动添加到 ListView 时保持滚动位置 的相关文章

随机推荐