android - RecyclerView 在插入时滚动

标签 android android-recyclerview chat reverse linearlayoutmanager

我正在尝试使用 RecyclerView 创建聊天应用程序。我正在使用带有 setReverseLayout(true)LinearLayoutManager

当我一直滚动到底部(即数据集开始 = 最新消息)并将新消息插入数据集中时,该项目按预期显示在列表底部( View 向上滚动为新项目腾出空间)。

我遇到的问题是当我向上滚动查看旧消息时。当一条新消息插入到数据集的开头时, View 会向上滚动大约一个消息高度,即使该消息甚至没有呈现,因为它超出了视口(viewport)的范围。

如何在 View 滚动到底部时保持滚动行为,但在滚动到旧消息时禁用它?

更新: 我还制作了一个小应用程序,重现了这个问题: https://github.com/ehehhh/RecyclerViewProblem

更新 2:我也提交了对我所做的 repo 有效的修复。

相关代码(希望):

compile 'com.android.support:recyclerview-v7:24.2.0'

XML:

<android.support.v7.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clipToPadding="false"
            android:paddingBottom="8dp"
            android:paddingTop="8dp"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

RecyclerView 初始化代码:

layoutManager = new LinearLayoutManager(context);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.setReverseLayout(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setScrollContainer(true);
recyclerView.setLayoutAnimation(null);
recyclerView.setItemAnimator(null);
adapter = new ChatAdapter(...);
recyclerView.setAdapter(adapter);

适配器:

public class ChatAdapter extends RecyclerView.Adapter<ChatViewHolder> {

    private List<MessageWrapper> dataset;

    public ChatAdapter(List<MessageWrapper> dataset, ...) {
        this.dataset = dataset;
        setHasStableIds(true);
    }

    ...

    @Override
    public long getItemId(int position) {
        return dataset.get(position).getId();
    }

    @Override
    public int getItemCount() {
        return dataset.size();
    }

    public void datasetChanged(List<MessageWrapper> dataset) {
        this.dataset = dataset;
        notifyDataSetChanged();
    }
}

当向数据集中添加新项目时,我只需调用适配器中的 datasetChanged 方法即可。

最佳答案

如果您知道项目已更改,则在 Recycler View 中使用 notifyDataSetChanged 是多余的 你可以使用

notifyItemInserted(position) 

在这种特殊情况下有效的是

 notifyItemInserted(0);

 notifyItemRangeInserted(positionStart, newItems.size() - 1)

这只会重新绑定(bind)此范围内的 View

检查 https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#notifyItemInserted(int)

关于android - RecyclerView 在插入时滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39326790/

相关文章:

android - RecyclerView 与 CardView

javascript - 如何在JS中向网页发送控制台命令?

android - 解码 Android Intent Parcelable 时找不到类

java - 安卓应用包名

android - Grid Recyclerview,偶数行有 3 列,奇数行有 4 列

android - recyclerview 在将新项目添加到列表时得到刷新

android - 使用 Smack API 的基于 XMPP 的消息传递应用程序的正确架构

java - 如何继续使用 jsp 和 servlet 制作聊天应用程序

android - PhoneGap 是我的正确选择吗?

java - 如何修改整个 ProgressBar?