【问题标题】:Adding items to Endless Scroll RecyclerView with a ReverseLayout recyclerview使用 ReverseLayout recyclerview 将项目添加到 Endless Scroll RecyclerView
【发布时间】:2016-03-25 03:19:24
【问题描述】:

在正常的回收视图中,最新的项目都在顶部,如果你将一个项目添加到回收视图中,它会将现有的项目向下推,新的项目占据顶部的位置。

在reverseLayout recyclerview 中,最新的项目都在底部,如果你将一个项目添加到recyclerview 中,它会被添加到底部。这种布局对于您希望最新的 cmets 位于底部的评论提要等内容非常有用。

例如,当您对朋友的状态发表评论时,Facebook 评论提要就是一个很好的例子。可以看到cmets都有贴在底部的时间,时间从上到下从12小时减少到10小时:

reverseLayout 很容易设置,我使用以下代码完成了它:

mLayoutManager = new LinearLayoutManager(this);
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);

然而,我正在努力附加一个反向无限滚动监听器。我正在使用我的问题中的以下 Vilen 代码(Adding items to Endless Scroll RecyclerView with ProgressBar at bottom)并对其进行修改,以便 onLoadMoreListener 仅在向上滚动而不是向下滚动时才会激活。您想向上滚动到较旧的 cmets:

    if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
        final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
        //if you add on addOnScrollListener, it will cause the scroll listener to be called twice each time you reset your adapter
        recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
            int firstVisibleItem;
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                final int currentFirstVisibleItem = linearLayoutManager.findFirstVisibleItemPosition();
                totalItemCount = linearLayoutManager.getItemCount();
                lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();

                if(lastVisibleItem > firstVisibleItem)
                {
                    Log.i("SCROLLING UP","TRUE");
                    if (!loading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
                        current_page++;
                        if (onLoadMoreListener != null) {
                            onLoadMoreListener.onLoadMore(current_page);
                        }
                        loading = true;
                    }
                }
                lastVisibleItem=firstVisibleItem;
            }
        });
    }

当 onLoadMoreListener 被调用时,我的 activity 类中调用了以下代码:

    CommentsAdapter.OnLoadMoreListener onLoadMoreListener = new CommentsAdapter.OnLoadMoreListener() {
    @Override
    public void onLoadMore(int current_page) {
        //get the firstCommentId on the list of comments so that we can send it to the server to fetch comments less than that comment id to display in our recyclerview
        firstCommentId = comments.get(0).getId();
        //add empty item for progress bar / wheel and display the progress bar / wheel
        Comment comment = new Comment();
        comment.setViewType(Constants.COMMENT_PROGRESS_BAR);
        comments.add(0, comment);
        mCommentAdapter.notifyItemInserted(0);
        mCommentAdapter.notifyItemRangeChanged(1, comments.size());

        //CODE FOR NETWORK OPERATIONS GOES HERE TO FETCH THE NEXT FEW COMMENTS WHEN SCROLLING UP//
    }
};

但是,当我向上滚动时,似乎根本没有调用 onLoadMoreListener。

我还确保我的提要中至少有 10 个 cmets,之前加载了 5 个,当我向上滚动时应该再加载 5 个。

有没有人知道我在使用这个反向 OnLoadMoreListener 时做错了什么?

编辑:

reverseLayout recyclerview 实际上可以使用 Vilen 的原始代码,我已经上传了一个 github repo 来展示这一点:

https://github.com/Winghin2517/ReverseLayoutRecyclerview

当 onLoadMoreListener 被激活时仍然存在问题 - 如果评论列表仅包含 3 个 cmets 并且没有更多 cmets 可以添加,我不希望 onLoadMoreListener 在我 最初查看我的 cmets - 当我第一次点击我的应用查看 cmets 时。现在,当我单击查看我的 cmets 时,即使 Dataset 中有 3 个 cmets,progressBar 仍会显示,并且在 2 秒后消失,我认为这是不必要的(请参阅我演示的 github repo)。

当只有 3 个 cmets 时禁用它也不是一个好主意,因为 onLoadMoreListener 就像一个 swipeToRefresh 对象。如果在用户查看评论提要之后有更多的 cmets,他可以向下滑动,onLoadMoreListener 将显示这些 cmets。

有没有办法在提要加载最初时禁用它?

【问题讨论】:

  • 嗨,Simon,我有几分钟空闲时间会去看看。平均时间确保您没有使用最后一个可见项目,而是在当前可见项目位置为 1 或 0 时触发刷新
  • 谢谢维伦。我一直在尝试不同的东西,但不幸的是我仍然无法让它正常工作。我已经增加了一笔赏金来增加交易。

标签: android android-recyclerview onscrolllistener


【解决方案1】:

Simon:我之前提出的解决方案here 可以很好地使用反向布局,无需任何修改。我要为反向布局添加的唯一内容是在您第一次显示时自动滚动到第一项,但这取决于您。 现在回到你有的问题。你提到当你滚动时没有任何反应。所以我的猜测是你以错误的顺序初始化你的 recycler 视图。确保你这样做

mLayoutManager = new LinearLayoutManager(this);
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);

mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new MyAdapter<>(myDataset, mRecyclerView);
mRecyclerView.setAdapter(mAdapter);

注意布局管理器首先被实例化,然后你设置它,然后你提供适配器。让我知道是否是这种情况。

编辑只是从下面的评论中提出这个:

忘记我们在onLoadMoreListener 中的内容,所有滚动内容只需使用标准RecyclerView 包裹在SwipeToRefreshLayout

【讨论】:

  • 嗨 Vilen,我实际上把你的初始代码放入了一个新的 android 项目中,它似乎与 recyclerview 的反向布局一起工作。我想我只是感到困惑,因为我虽然数据的顺序会改变,例如,而不是 cmets.add(0, comment);,我会添加 cmets.add(cmets.size(), comment);因为列表颠倒了。一切都非常混乱。我确实对您的代码有一个额外的问题,这似乎会在初始加载时影响 reverseLayout recyclerview。你能看看我的编辑吗?
  • 嗨 Simon,cmets.add(0, comment) revers 布局没有什么令人困惑的地方,它意味着只有布局反转而不是数据集反转,它只是开始向后渲染。关于您的编辑,我不确定您实际需要什么行为。如果有 3 个项目你想要它做什么?如果随后有更多项目,您的程序将如何知道呢?你想让它加载更多还是不加载。以及何时需要加载更多项目?
  • 所以我的意思是,如果您的项目数量少于触发 onLoadMoreListener 的数量,则在初始加载时根本不应该显示进度条。在我的 github 存储库中,我们最初只有 3 个项目,所以我根本没想到会看到进度条,因为没有更多项目要加载。如果随后有更多项目,那么我想手动将 recyclerview 向下拖动,这将触发侦听器加载更多。 onLoadMoreListener 应该只在您手动向下拖动时激活,而不是在您打开应用程序时激活。
  • 好的,然后忘记我们在 onLoadMoreListener 中拥有的东西,所有滚动的东西只使用 SwipeToRefreshLayout 中包装的标准回收器视图
  • 我认为取出 onLoadMoreListener 对我来说效果更好 - 无论如何谢谢。听众我还有另一个问题,你介意在这里看看吗:stackoverflow.com/questions/34953260/…?它与 API 在现实世界中返回的不同大小的数据集有关
【解决方案2】:

我真的不想在最后使用 SwipeToRefreshLayout,因为当您有评论提要时它看起来不太好。

所以我所做的是修改 onLoadMoreListener 方法,以便它检测活动首次启动的时间。如果是第一次启动,我们不希望显示进度条:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
            if (savedInstanceState == null) {
                                initial = true;
            }
}

然后我们将使用初始布尔变量来判断activity是否刚刚启动并禁用进度条。

    @Override
    public void onLoadMore(int current_page) {
        //add progress item
        if (initial) {
            //we do not add the progress bar when the activity opens initially so
            //we do nothing. We just change the variable to false so going forward, you will add a progress bar each time you refresh
            initial = false;
        } else {
            comments.add(createProgressBar());
            mCommentAdapter.notifyItemInserted(comments.size()-1);
        }

【讨论】:

    猜你喜欢
    • 2015-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    相关资源
    最近更新 更多