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

时间:2017-11-12 16:05:59

标签: android android-recyclerview linearlayoutmanager

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

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

adapter = new RecyclerViewAdapter(data, recyclerView);
recyclerView.setAdapter(adapter);

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

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

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

关于可能出现什么问题的任何想法?我在片段中使用RecyclerView。这可能是问题的原因吗?

RecyclerView

的.xml文件
<?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>

9 个答案:

答案 0 :(得分:4)

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

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

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

recyclerView.setAdapter(adapter);

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

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

  private List<Data> mData;

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

  ...
}

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

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

adapter = new RecyclerViewAdapter(data);
recyclerView.setAdapter(adapter);

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

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

  private List<Data> mData;
  ...

  public void addItem(Data datum) {
    mData.add(datum);
    notifyItemInserted(mData.size());
  }
}

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

adapter.addItem(newData);
recyclerView.scrollToPosition(adapter.getItemCount() - 1);

请记住,您需要覆盖适配器中的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();
  }

  ...
}

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

答案 1 :(得分:2)


  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);
            }
        }
    })

答案 2 :(得分:1)

ישואוהבאותך的解决方案适用于其他项目。但设置recyclerView.scrollToPosition()对我不起作用。这就是最终的工作:

public void addNewCard() {
    data.add("New");
    adapter.notifyItemInserted(data.size());

    scrollView.post(new Runnable() {
        @Override
        public void run() {
            scrollView.scrollTo(0,buttonAddNewItem.getTop());
        }
    });
}

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

也许这会帮助某人

@Override
public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
    if (pingAdapter != null) {

        Ping ping = dataSnapshot.getValue(Ping.class);
        pingAdapter.pings.add(ping);
        recyclerView.smoothScrollToPosition(pingAdapter.getItemCount());

        pingAdapter.notifyDataSetChanged();
    }
}
recyclerView.smoothScrollToPosition(pingAdapter.pings.size());

甚至更快

答案 5 :(得分:0)

这是因为您的

recyclerView.scrollToPosition(data.size()-1);

首先被调用,然后列表被初始化。初始化“回收者视图”视图后,需要添加此行。您可以在处理程序中添加此行。

答案 6 :(得分:0)

这对我有用。

adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
        override fun onChanged() {
            super.onChanged()
            if (canShowLive()) wvl_log_rv.scrollToPosition(adapter.itemCount - 1)
        }
 })

经过测试并验证

答案 7 :(得分:0)

或者,如果您将 ListAdapter 与 DiffUtill 一起使用并通过 submitList() 提交新列表,则可以使用 ListAdapter 的 onCurrentListChanged。例如:

override fun onCurrentListChanged(previousList: MutableList<Item>, currentList: MutableList<Item>) {
    super.onCurrentListChanged(previousList, currentList)
     //E.g. check if new item has been added
    if (currentList.size == previousList.size + 1) {
        recyclerView.scrollToPosition(currentList.size - 1)
    }
}

答案 8 :(得分:-1)

我有同样的问题。在我的RecyclerView中添加项目时,recyclerView没有滚动到最底层的项目。

但这种方式对我有用。

rowList.add(dataRetrieved);
mRecyclerView.scrollToPosition(rowList.size()-1);
myAdapter.notifyDataSetChanged();

诀窍是在正确的位置使用scrollToPosition()方法。