使用ProgressBar将项目添加到Endless Scroll RecyclerView底部

我跟随Vilen在SO上的出色答案: 在RecyclerView网格中添加一个不确定的进度条作为页脚,以便如何使用ProgressBar实现无限循环滚动视图。

我自己实现它,它的工作原理,但我想扩大这个例子。 我想在回收站顶部添加额外的项目,就像Facebook添加新的状态更新一样。

我无法成功添加额外的项目 – 这里是我的代码,我添加到他的MainActivity Vilen的代码:

@Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.add) { myDataset.add(0, "Newly added"); mRecyclerView.smoothScrollToPosition(0); mAdapter.notifyItemInserted(0); } return super.onOptionsItemSelected(item); } 

当我点击“添加”button时:

添加一个新项目

当我向下滚动时,我得到两个纺纱者,而不是一个:

向下滚动

当纺纱工完成,接下来的5件物品被装上时,纺纱工仍然在那里:

在微调之后

我究竟做错了什么?

Solutions Collecting From Web of "使用ProgressBar将项目添加到Endless Scroll RecyclerView底部"

问题是,当你添加新的项目内部EndlessRecyclerOnScrollListener不知道它和计数器打破。 事实上, EndlessRecyclerOnScrollListener回答有一些限制和可能的问题,例如,如果一次加载1个项目,它将不起作用。 所以这里是一个增强版本。

  1. 摆脱EndlessRecyclerOnScrollListener我们不再需要它了
  2. 将您的适配器更改为包含滚动侦听器的适配器

     public class MyAdapter<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private final int VIEW_ITEM = 1; private final int VIEW_PROG = 0; private List<T> mDataset; // The minimum amount of items to have below your current scroll position before loading more. private int visibleThreshold = 2; private int lastVisibleItem, totalItemCount; private boolean loading; private OnLoadMoreListener onLoadMoreListener; public MyAdapter(List<T> myDataSet, RecyclerView recyclerView) { mDataset = myDataSet; if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) { final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); totalItemCount = linearLayoutManager.getItemCount(); lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition(); if (!loading && totalItemCount <= (lastVisibleItem + visibleThreshold)) { // End has been reached // Do something if (onLoadMoreListener != null) { onLoadMoreListener.onLoadMore(); } loading = true; } } }); } } @Override public int getItemViewType(int position) { return mDataset.get(position) != null ? VIEW_ITEM : VIEW_PROG; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { RecyclerView.ViewHolder vh; if (viewType == VIEW_ITEM) { View v = LayoutInflater.from(parent.getContext()) .inflate(android.R.layout.simple_list_item_1, parent, false); vh = new TextViewHolder(v); } else { View v = LayoutInflater.from(parent.getContext()) .inflate(R.layout.progress_item, parent, false); vh = new ProgressViewHolder(v); } return vh; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder instanceof TextViewHolder) { ((TextViewHolder) holder).mTextView.setText(mDataset.get(position).toString()); } else { ((ProgressViewHolder) holder).progressBar.setIndeterminate(true); } } public void setLoaded() { loading = false; } @Override public int getItemCount() { return mDataset.size(); } public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) { this.onLoadMoreListener = onLoadMoreListener; } public interface OnLoadMoreListener { void onLoadMore(); } public static class TextViewHolder extends RecyclerView.ViewHolder { public TextView mTextView; public TextViewHolder(View v) { super(v); mTextView = (TextView) v.findViewById(android.R.id.text1); } } public static class ProgressViewHolder extends RecyclerView.ViewHolder { public ProgressBar progressBar; public ProgressViewHolder(View v) { super(v); progressBar = (ProgressBar) v.findViewById(R.id.progressBar); } } } 
  3. 更改Activity类中的代码

     mAdapter = new MyAdapter<String>(myDataset, mRecyclerView); mRecyclerView.setAdapter(mAdapter); mAdapter.setOnLoadMoreListener(new MyAdapter.OnLoadMoreListener() { @Override public void onLoadMore() { //add progress item myDataset.add(null); mAdapter.notifyItemInserted(myDataset.size() - 1); handler.postDelayed(new Runnable() { @Override public void run() { //remove progress item myDataset.remove(myDataset.size() - 1); mAdapter.notifyItemRemoved(myDataset.size()); //add items one by one for (int i = 0; i < 15; i++) { myDataset.add("Item" + (myDataset.size() + 1)); mAdapter.notifyItemInserted(myDataset.size()); } mAdapter.setLoaded(); //or you can add all at once but do not forget to call mAdapter.notifyDataSetChanged(); } }, 2000); System.out.println("load"); } }); 

其余的保持不变,让我知道这是否适合你。

我想我知道了。

我忘了调用notifyItemRangeChanged。

 @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.add) { myDataset.add(0, "Newly added"); mAdapter.notifyItemInserted(0); mAdapter.notifyItemRangeChanged(1, myDataset.size()); mRecyclerView.smoothScrollToPosition(0); } return super.onOptionsItemSelected(item); } 

一旦你添加了代码,代码就可以工作了,但是,你会看到,在微调完成旋转后,项目号码不会正确地递增。

增量

这是因为上面的“新增”项作为实际项目(我们可以称之为“项目0”),并且这导致增量像21一样被跳过,但是实际上编号21已经变成项目0换句话说,第22项之前有21个实际项目。