关于java:当已经在底部并添加新项目时,将recyclerView保持在底部

Keep recyclerView at bottom when already at bottom and new item is added

我正在创建一个聊天应用程序。当列表中的当前最低项目在屏幕上可见时,我试图让所有新消息出现在聊天应用程序的底部,但当用户向上滚动时(如大多数聊天应用程序)则不会。截至目前,当屏幕上仍有未使用的空间时,我已经让它工作了,但是当 RecyclerView 有太多视图无法容纳时,它开始将新消息放置到屏幕底部。这是我创建 RecyclerView 的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private void initRecyclerView() {


    mRecyclerView = findViewById(R.id.chatRecyclerView);
    mAdapter = new ChatRecyclerViewAdapter(this, mMessages, mUsernames, mRoomID, mDatabaseReference);
    mRecyclerView.setAdapter(mAdapter);
    final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
    linearLayoutManager.setStackFromEnd(true);
    RecyclerView.AdapterDataObserver observer = new RecyclerView.AdapterDataObserver() {
        @Override
        public void onChanged() {
            super.onChanged();

            if(linearLayoutManager.findLastVisibleItemPosition()==(mAdapter.getItemCount()-1)){
                mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount()-1);
            }
        }
    };
    mAdapter.registerAdapterDataObserver(observer);
    mRecyclerView.setLayoutManager(linearLayoutManager);

我最终添加了一个检查以查看 RecyclerView 是否位于底部,并将该布尔值插入 AdapterDataObserver。我还犯了使用观察者的 onChanged 方法而不是 onItemRangeInserted 的错误,这显然是补充 RecyclerViewAdapter 中的 notifyItemInserted 所必需的。

这是我的 RecyclerView 的工作代码,如果用户位于底部,它会自动将新消息放置在底部:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
 private void initRecyclerView() {
   

    //initializes and sets adapter
   

    mRecyclerView = findViewById(R.id.chatRecyclerView);
    mAdapter = new ChatRecyclerViewAdapter(this, mMessages, mUsernames, mRoomID, mDatabaseReference);
    mRecyclerView.setAdapter(mAdapter);

    //Creates layout manager and makes it feed new RecyclerView views from the bottom


    final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
    linearLayoutManager.setStackFromEnd(true);

    //Makes RecyclerView scroll to bottom when notifyItemInserted is called from adapter and RecyclerView is already at bottom

    RecyclerView.AdapterDataObserver observer = new RecyclerView.AdapterDataObserver() {
        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            super.onItemRangeInserted(positionStart, itemCount);


            if (isAtBottom) {
                mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount() - 1);
            }
        }
    };

    //Adds logic to see if RecyclerView is at bottom or not

    mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);

            if (!recyclerView.canScrollVertically(1)) {
                isAtBottom = true;
            } else {
                isAtBottom = false;
            }
        }
    });

    //Assigns observer to adapter and LayoutManager to RecyclerView

    mAdapter.registerAdapterDataObserver(observer);
    mRecyclerView.setLayoutManager(linearLayoutManager);

}

mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount()-1); // 删除这一行。

并使用这个:

1
mAdapter.notifyItemRangeInserted(mAdapter.getItemCount(), list.size() - 1);