当数据加载完成后,RecyclerView 滚动到底部

19

自从我改变了我的应用程序以从Room数据库加载数据后,我在RecyclerView上遇到了一些奇怪的问题。

我有一个屏幕(一个Fragment),用于显示用户的个人资料。基本上,它是一个GridLayout,第一项(行)显示用户的一些信息,然后对于每一行,我都显示三张图片。

RecyclerView的代码如下:

private void initializeRecyclerView() {
    if (listAdapter == null) {
        listAdapter = new PhotosListAdapter(getActivity(), userProfileAccountId, false);
    }

    rvPhotosList.setNestedScrollingEnabled(true);
    rvPhotosList.getItemAnimator().setChangeDuration(0);

    GridLayoutManager layoutManager = new GridLayoutManager(getContext(), ProfileFragment.GRID_COLUMNS,
            LinearLayoutManager.VERTICAL, false);

    layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
        @Override
        public int getSpanSize(int position) {
            // 3 spans for Header, 1 for photos
            return listAdapter.isHeader(position) ? 3 : 1;
        }
    });

    rvPhotosList.setLayoutManager(layoutManager);

    int spacingInPixels = 1dp;
    rvPhotosList.addItemDecoration(new PaddingItemDecoration(GRID_COLUMNS, spacingInPixels, true));

    rvPhotosList.setAdapter(listAdapter);
}

这就是我如何加载数据:

    compositeDisposable.add(
        repository.getAccount(accountId)
            .doOnNext(account -> {
                if (account != null && view != null) {
                    view.showCover(account.getCover());
                    view.showAccount(account);
                }
            })
            .flatMap(s -> repository.getUserPosts(accountId))
            .subscribe(posts -> {
                if (view != null) {
                    view.showPosts(posts);
                }
            }, throwable -> {}));
两个调用都返回一个Flowable,其中一个是Flowable<Account>,另一个是Flowable<Post>,其中Account和Post是Room的实体类。 两个方法showAccount()和showPosts()将之前提到的实体类传递给适配器。
问题是:数据加载完成后,它会滚动到屏幕底部(也是RecyclerView底部)。
我不确定为什么会发生这种情况。是因为Room的Flowable类型吗?因为以前当我从网络获取数据并将它们传递给适配器时,我没有遇到这个问题。
编辑:我正在使用版本25.3.1的RecyclerView。
编辑2:这是我如何使用Account和Post数据更新我的适配器类的:
public void addPhotos(List<Post> posts) {
    dataset.addAll(posts);
    notifyDataSetChanged();
}

public void addProfileItem(Account account) {
    this.account = account;
    notifyItemInserted(0);
}

1
这个问题已经在stackoverflow上得到了解答:https://dev59.com/m1kT5IYBdhLWcg3wL8r3 - Akhil
4个回答

36

你尝试过这个吗?将父RecyclerViewdescendantFocusability属性设置为blocksDescendants

这样做的效果是,不再关注于RecyclerView中动态加载的子视图,从而自动滚动也不会发生。

android:descendantFocusability="blocksDescendants"

注意: 属性descendantFocusability也可以与其他视图一起使用,例如FrameLayout、RelativeLayout等。因此,如果您将此属性设置为父/根布局,则不会再滚动到底部。


1
这将停止recyclerView项目中的触摸。 - Abubakar
1
@Abubakar 不是的。它只是在开始加载项目到RV时阻止后代先获得焦点。 - Arpit J.
1
如果您在“heaerRow”中有EditText,则会阻止它。 - David
这对我有用。我在另一个可回收视图的行内有一个可回收视图。这会阻止它自动滚动到该行。 - sudoExclaimationExclaimation

1
如果您有一些初始项,这些项目应在加载新项目后放置在底部,那么您需要给它们分配新的ID,如果您不想将滚动器重新滚动到底部。这是因为滚动器记住了这些项目在更新前对用户可见,在更新后恢复其状态,以便在底部显示初始项目。

0
虽然这个问题有点老了,似乎没有一个正确的答案。我认为你在这里需要做的是监听适配器的变化,然后在每次检测到变化时滚动到底部。
这是一个可行的示例。
listAdapter?.registerAdapterDataObserver(object : AdapterDataObserver() {
    override fun onChanged() {
        rvPhotosList?.smoothScrollToPosition(listAdapter?.itemCount ?: 0)
    }
})

0
在我的情况下,这行代码是罪魁祸首,
GridLayoutManager gridLayoutManager = new GridLayoutManager(this, SPAN_COUNT, GridLayoutManager.VERTICAL, true);

具体来说,就是将最后一个参数 reverseLayout 的属性设置为 true。如果将其设置为 false,RecyclerView 就不会滚动到屏幕底部。

正如您在问题中所看到的,该值已经是false。然而,在您确实需要设置reverseLayout属性为true的情况下,这并不是一个解决方案。 - IIRed-DeathII

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