调用notifydatasetchanged后,Recyclerview如何滚动到顶部

4
我有一个水平的RecyclerView(使用LinearLayoutManager),其子项具有包装在RelativeLayout中的ImageView。RecyclerView有三行横向排列的子项。当滚动RecyclerView时,我会更新来自HTTP请求响应的数据集,并在HTTP响应回调中调用notifyDataSetChanged。如果RecyclerView的子项高度和宽度是固定值(例如150dp,84dp),则RecyclerView的行为符合预期,即加载新项并保持相同的滚动位置;但是,如果我将RecyclerView的子项高度和宽度设置为match_parent和wrap_content,则RecyclerView会完全刷新并滚动到第一个位置。为什么会发生这种情况?
注意:我查看了stackoverflow上的其他类似问题,但没有一个提供可行的解决方案。
main_layout
<android.support.v7.widget.RecyclerView
    android:id="@+id/grid_recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginBottom="110dp"
    android:layout_marginLeft="15dp"
    android:layout_marginTop="80dp"
    android:background="@color/transparent"
    android:outlineProvider="bounds"
    android:elevation="8dp"
    android:padding="0dp"
    android:scrollbars="none" />
....

recycler_view_child_item

<RelativeLayout      xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="0dp">
<ImageView
    android:id="@+id/thumbnail"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:adjustViewBounds="true"
    android:maxWidth="126dp"
    android:maxHeight="225dp"
    android:padding="0dp"/>
</RelativeLayout>

你找到任何解决方案了吗? - hamid Mahmoodi
4个回答

8

我曾经遇到过同样的问题,但在stackoverflow上也找不到解决方案。问题是由于没有为RecyclerView设置LayoutManager引起的。我知道你说你有一个LinearLayoutManager,但请确保按照以下方式设置它。(在我的情况下,我正在使用HorizontalGridView,但同样的原理适用于RecyclerView)。

horizontalGridView = (HorizontalGridView) findViewById(R.id.gridView);
GridElementAdapter adapter = newGridElementAdapter(VenueProfileActivity.this, mDeals);
horizontalGridView.setAdapter(adapter);

HorizontalGridView.LayoutManager layoutManager = new LinearLayoutManager(VenueProfileActivity.this, LinearLayoutManager.HORIZONTAL, false);
horizontalGridView.setLayoutManager(layoutManager);
horizontalGridView.setHasFixedSize(true);

你是救命恩人,谢谢! - Farhan Fuad

0

我遇到了同样的问题,并发现mossy321提供的答案很有用,但并不能完全解决我的问题。在我的应用程序中,我有一系列对象,每个都有一个需要每30秒增加一次的时间。我在托管Fragment中运行了一个计时器,但更新数据导致了跳跃问题。

我的回收代码如下:

 orderRecycler = (RecyclerView) rootView.findViewById(R.id.order_recycler_view);
    // use this setting to improve performance if you know that changes
    // in content do not change the layout size of the RecyclerView
    orderRecycler.setHasFixedSize(true);

    //Stops items doing a default flashing animation on individual refresh
    RecyclerView.ItemAnimator animator = orderRecycler.getItemAnimator();
    if (animator instanceof SimpleItemAnimator) {
        ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
    }

    orderLayoutManager = new LinearLayoutManager(getActivity());
    orderRecycler.setLayoutManager(orderLayoutManager);
    orderAdapter = new OrderAdapter(orderArrayList, historyArrayList, getActivity());

    orderRecycler.setAdapter(orderAdapter);

这里需要注意的是setHasFixedSize非常关键。我猜测在数据改变时,系统必须重新绘制视图,从而导致跳转到顶部的问题,但如果它知道它们将是相同的大小,那么它只需在这种情况下更新更改的文本。

另一个问题是我不能使用notifyDatasetChanged,否则仍会导致相同的问题。我必须为每个项目单独通知。这就是在回收器声明中使用项动画器的原因。如果没有它,项目将在更新时闪烁。

 for(int i = 0; i < orderArrayList.size(); i++){
                orderAdapter.notifyItemChanged(i);
            }

0

刷新可能是因为您没有指定子视图的大小。我会首先删除RelativeLayout,因为它似乎没有任何作用,这样可以减少视图深度。此外,如果recyclerView的子视图始终具有相同的大小,请在子视图本身上设置它,而不是父视图(即recyclerView)。另外,您是否在recyclerView上将setHasFixedSize设置为true?


移除了相对布局。因为我将RecyclerView的大小设置为与父视图匹配并带有一些边距,所以RecyclerView的大小可能因设备而异。因此,我无法为子视图设置固定大小。RecyclerView有三行,因此我将子视图的高度设置为与父视图匹配,宽度设置为包裹内容,以避免在RecyclerView中的子视图之间留下任何空白。 - Neanderthal
另外,我已将setHasFixedSize设置为true。 - Neanderthal

-3

当您调用notifyDataSetChanged时,可以将RecyclerView滚动到特定位置

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接