RecyclerView在添加新项目时滚动到位置

Ars*_*suf 13 android android-recyclerview linearlayoutmanager

当新项目添加到列表时,我希望我的RecyclerView滚动到底部.以下是我的代码:

RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);

adapter = new RecyclerViewAdapter(data, recyclerView);
recyclerView.setAdapter(adapter);
Run Code Online (Sandbox Code Playgroud)

当我点击下面的按钮时RecyclerView,数据会添加到列表中:

public void addNewCard() {
    data.add("New");
    adapter.notifyItemInserted(data.size() - 1);
    recyclerView.scrollToPosition(data.size() - 1);
}
Run Code Online (Sandbox Code Playgroud)

每当我添加一个项目时,它总是会滚动到最顶端的位置.我尝试使用smoothScrollToPosition(),并尝试使用scrollToPosition()LinearLayoutManager了.我甚至尝试过使用ViewTreeObserver.尝试更改RecyclerView依赖项的版本.我在Stack Overflow上进行了彻底搜索,没有一个解决方案适合我.

关于什么可能是问题的任何想法?我在RecyclerView片段里面使用.这可能是问题的原因吗?

我的.xml文件 RecyclerView

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView 
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scroll_view_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent">

<RelativeLayout
    android:id="@+id/rel_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="6dp" />

    <Button
        android:id="@+id/button_add_new_card"
        style="@style/Widget.AppCompat.Button.Borderless"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/listView"
        android:layout_marginBottom="16dp"
        android:layout_marginTop="8dp"
        android:padding="20dp"
        android:text="+ Add new Item" />
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
Run Code Online (Sandbox Code Playgroud)

ישו*_*ותך 8

如果要将数据添加到列表的底部,则需要setStackFromEnd()在RecyclerView布局管理器中使用。

但是首先,您需要修复适配器。您不得将RecylerView传递给适配器。因此以下代码是错误的:

...
// This is wrong!!
adapter = new RecyclerViewAdapter(data, recyclerView);

recyclerView.setAdapter(adapter);
Run Code Online (Sandbox Code Playgroud)

您需要更改Adapter构造函数以仅接收数据作为其参数。像这样:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {

  private List<Data> mData;

  public RecyclerViewAdapter(List<Data> data) {
    this.mData = data;
  }

  ...
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用以下代码将数据设置为始终添加在最后一个底部:

LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(linearLayoutManager);

adapter = new RecyclerViewAdapter(data);
recyclerView.setAdapter(adapter);
Run Code Online (Sandbox Code Playgroud)

要添加新数据,最好在适配器中制作新方法。像这样:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {

  private List<Data> mData;
  ...

  public void addItem(Data datum) {
    mData.add(datum);
    notifyItemInserted(mData.size());
  }
}
Run Code Online (Sandbox Code Playgroud)

每当添加新数据时,都需要使用scrollToPosition方法滚动到底部。像这样:

adapter.addItem(newData);
recyclerView.scrollToPosition(adapter.getItemCount() - 1);
Run Code Online (Sandbox Code Playgroud)

请记住,您需要getItemCount()在适配器中覆盖。应该是这样的:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {

  private List<Data> mData;
  public RecyclerViewAdapter(List<Data> data) {
    this.mData = data;
  }

  // Return the total count of items
  @Override
  public int getItemCount() {
    return mData.size();
  }

  ...
}
Run Code Online (Sandbox Code Playgroud)

请注意,我在这里使用Data pojo作为示例。您需要根据您的数据类型进行更改。

  • 谢谢你。但是这个我试过了,还是不行! (3认同)

小智 8

adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
    override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
        super.onItemRangeInserted(positionStart, itemCount)

        val msgCount = adapter.getItemCount()
        val lastVisiblePosition = 
            linearLayoutManager.findLastCompletelyVisibleItemPosition()

        if (lastVisiblePosition == -1 || positionStart >= msgCount - 1 && 
            lastVisiblePosition == positionStart - 1) {
            recyclerView.scrollToPosition(positionStart)
        } else {
            recyclerView.scrollToPosition(adapter.getItemCount() - 1);
        }
    }
})
Run Code Online (Sandbox Code Playgroud)


Bri*_*pin 5

这是我想出的解决方案,对于基础知识来说已经足够了,并且不需要任何自定义适配器。

myAdapter.registerAdapterDataObserver(object :
        RecyclerView.AdapterDataObserver() {
        override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
            myRecyclerView.scrollToPosition(positionStart)
        }
    })
Run Code Online (Sandbox Code Playgroud)

  • 如果您使用分页,请检查“positionStart != 0”,然后滚动 (2认同)