android - ejemplo - Agregar elementos a Endless Scroll RecyclerView con ProgressBar en la parte inferior
cardview android ejemplo (2)
Creo que lo descubrí.
Olvidé llamar a 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);
}
Una vez que lo agregue, el código funcionará; sin embargo, verá que una vez que el girador termina de girar, el número del artículo no aumentará correctamente.
Esto se debe a que el elemento "Nuevamente agregado" en la parte superior cuenta como un elemento real (podemos llamarlo "Artículo 0"), y esta causa porque el incremento para cambiar por 1 como 21 se ha omitido, pero en realidad el número 21 se ha convertido en Artículo 0 En otras palabras, hay 21 elementos reales antes del Artículo 22.
Seguí la excelente respuesta de Vilen en SO: coloque una barra de progreso indeterminada como pie de página en una cuadrícula de RecyclerView sobre cómo implementar una vista de reciclador de rollos sin fin con ProgressBar.
Lo implementé yo mismo y funciona, pero me gustaría extender el ejemplo. Quiero agregar elementos adicionales en la parte superior de la vista de reciclador, similar a cómo lo hace Facebook cuando agrega una nueva actualización de estado.
No pude agregar elementos adicionales a la lista con éxito; aquí está mi código que agregué al código de Vilen en su actividad principal:
@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);
}
Cuando hice clic en el botón "Agregar":
Cuando me desplazo hacia abajo, obtengo dos spinners en lugar de uno:
Cuando los hilanderos terminan y los 5 elementos siguientes se cargan, la ruleta todavía está allí:
¿Qué estoy haciendo mal?
El problema es que cuando agrega un nuevo elemento interno, EndlessRecyclerOnScrollListener
no lo conoce y los contadores se rompen. Como cuestión de hecho, responder con EndlessRecyclerOnScrollListener
tiene algunas limitaciones y posibles problemas, por ejemplo, si carga 1 elemento a la vez, no funcionará. Entonces aquí hay una versión mejorada.
- Deshágase de
EndlessRecyclerOnScrollListener
ya no lo necesitamos Cambie su adaptador a este que contiene oyente de desplazamiento
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); } } }
Cambiar el código en la clase de actividad
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"); } });
El resto no cambia, avíseme si esto funciona para usted.