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); } |
并使用这个:
1 | mAdapter.notifyItemRangeInserted(mAdapter.getItemCount(), list.size() - 1); |