使用 ReverseLayout recyclerview 将项目添加到 Endless Scroll RecyclerView
Adding items to Endless Scroll RecyclerView with a ReverseLayout recyclerview
在普通的 recyclerview 中,最新的项目都在顶部,如果您将一个项目添加到 recyclerview 中,它会将现有项目向下推,新项目占据顶部位置。
在 reverseLayout recyclerview 中,最新的项目都在底部,如果您将项目添加到 recyclerview 中,它会添加到底部。这种布局对于评论提要等您希望最新评论位于底部的内容非常有用。
这方面的一个很好的例子是当您对朋友的状态发表评论时的 Facebook 评论提要。可以看到评论都在最下面有发表时间,从上到下时间从12小时递减到10小时:
reverseLayout 很容易设置,我已经使用以下代码完成了它:
mLayoutManager = new LinearLayoutManager(this);
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);
然而,我正在努力附加一个反向无限滚动侦听器。我使用了我的问题中的以下 Vilen 代码 () 并对其进行了修改,以便 onLoadMoreListener 仅在向上滚动而不是向下滚动时激活自身。您想向上滚动到较早的评论:
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中调用了如下代码class:
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 似乎根本没有被调用。
我还确保我的 Feed 中至少有 10 条评论,之前加载了 5 条,向上滚动时应该加载另外 5 条。
有人知道我在这个反向 OnLoadMoreListener 上做错了什么吗?
编辑:
reverseLayout recyclerview 实际上确实可以使用 Vilen 的原始代码,我已经上传了一个 github 回购来展示这一点:
https://github.com/Winghin2517/ReverseLayoutRecyclerview
当 onLoadMoreListener 激活时仍然存在问题 - 如果评论列表仅包含 3 条评论并且没有更多评论可添加,我根本不希望 onLoadMoreListener 在我时激活最初查看我的评论 - 当我第一次点击我的应用程序查看评论时。现在,当我点击查看我的评论时,即使数据集中有 3 条评论,progressBar 仍然显示并且在我认为没有必要的 2 秒后消失(参见我演示的 github repo这个)。
当只有 3 个评论时禁用它也不是一个好主意,因为 onLoadMoreListener 就像一个 swipeToRefresh 对象。如果用户在查看评论提要后有更多评论,他可以向下滑动,onLoadMoreListener 将显示这些评论。
有没有办法在 Feed 最初加载时禁用它?
Simon:我之前提出的解决方案 无需任何修改即可在反向布局中正常工作。我唯一要为反向布局添加的是在您第一次显示时自动滚动到第一个项目,但这取决于您。
现在回到你遇到的问题。你提到当你滚动时没有任何反应。所以我的猜测是您以错误的顺序初始化了您的 recylcer 视图。确保你这样做
mLayoutManager = new LinearLayoutManager(this);
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new MyAdapter<>(myDataset, mRecyclerView);
mRecyclerView.setAdapter(mAdapter);
注意布局管理器首先被实例化,然后设置它,然后提供适配器。让我知道是否是这种情况。
编辑 刚刚从下面的评论中提出这个:
forget about what we have with onLoadMoreListener
and all scrolling stuff just use standard RecyclerView
wrapped in SwipeToRefreshLayout
我真的不想在最后使用 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);
}
在普通的 recyclerview 中,最新的项目都在顶部,如果您将一个项目添加到 recyclerview 中,它会将现有项目向下推,新项目占据顶部位置。
在 reverseLayout recyclerview 中,最新的项目都在底部,如果您将项目添加到 recyclerview 中,它会添加到底部。这种布局对于评论提要等您希望最新评论位于底部的内容非常有用。
这方面的一个很好的例子是当您对朋友的状态发表评论时的 Facebook 评论提要。可以看到评论都在最下面有发表时间,从上到下时间从12小时递减到10小时:
reverseLayout 很容易设置,我已经使用以下代码完成了它:
mLayoutManager = new LinearLayoutManager(this);
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);
然而,我正在努力附加一个反向无限滚动侦听器。我使用了我的问题中的以下 Vilen 代码 (
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中调用了如下代码class:
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 似乎根本没有被调用。
我还确保我的 Feed 中至少有 10 条评论,之前加载了 5 条,向上滚动时应该加载另外 5 条。
有人知道我在这个反向 OnLoadMoreListener 上做错了什么吗?
编辑:
reverseLayout recyclerview 实际上确实可以使用 Vilen 的原始代码,我已经上传了一个 github 回购来展示这一点:
https://github.com/Winghin2517/ReverseLayoutRecyclerview
当 onLoadMoreListener 激活时仍然存在问题 - 如果评论列表仅包含 3 条评论并且没有更多评论可添加,我根本不希望 onLoadMoreListener 在我时激活最初查看我的评论 - 当我第一次点击我的应用程序查看评论时。现在,当我点击查看我的评论时,即使数据集中有 3 条评论,progressBar 仍然显示并且在我认为没有必要的 2 秒后消失(参见我演示的 github repo这个)。
当只有 3 个评论时禁用它也不是一个好主意,因为 onLoadMoreListener 就像一个 swipeToRefresh 对象。如果用户在查看评论提要后有更多评论,他可以向下滑动,onLoadMoreListener 将显示这些评论。
有没有办法在 Feed 最初加载时禁用它?
Simon:我之前提出的解决方案
mLayoutManager = new LinearLayoutManager(this);
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new MyAdapter<>(myDataset, mRecyclerView);
mRecyclerView.setAdapter(mAdapter);
注意布局管理器首先被实例化,然后设置它,然后提供适配器。让我知道是否是这种情况。
编辑 刚刚从下面的评论中提出这个:
forget about what we have with
onLoadMoreListener
and all scrolling stuff just use standardRecyclerView
wrapped inSwipeToRefreshLayout
我真的不想在最后使用 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);
}