Sí. Trataré de responder su caso mostrando cómo lo hice, y mostraré un ejemplo para su caso debajo de mi muestra del código.
Básicamente, para lograr esto, debe hacer un seguimiento de la posición de los Fragmentos. A continuación se muestra la implementación que utilicé para mi FragmentPagerAdapter
, que utiliza una ArrayList como fuente de datos.
public class MyFragmentPagerAdapter extends FragmentPagerAdapter {
private HashMap<Long, Fragment> mItems
= new HashMap<Long, Fragment>();
private ArrayList<MyObject> dataset;
public MyFragmentPagerAdapter(ArrayList<MyObject> objects) {
this.dataset = objects;
}
@Override
public int getCount() {
return dataset.size();
}
@Override
public Fragment getItem(int position) {
long id = getItemId(position);
if(mItems.get(id) != null) {
// caching to prevent multiple instances of the same fragment
// for the same position/id
return mItems.get(id);
}
Fragment f = Fragment.newInstance();
mItems.put(id, f);
return f;
}
@Override
public long getItemId(int position) {
// return a unique id
return dataset.get(position).getUniqueId();
}
@Override
public int getItemPosition(Object object) {
/*
* Purpose of this method is to check whether an item in the adapter
* still exists in the dataset and where it should show.
* For each entry in dataset, request its Fragment.
*
* If the Fragment is found, return its (new) position. There's
* no need to return POSITION_UNCHANGED; ViewPager handles it.
*
* If the Fragment passed to this method is not found, remove all
* references and let the ViewPager remove it from display by
* by returning POSITION_NONE;
*/
Fragment f = (Fragment) object;
for(int i = 0; i < getCount(); i++) {
Fragment item = (Fragment) getItem(i);
if(item.equals(f)) {
// item still exists in dataset; return position
return i;
}
}
// if we arrive here, the data-item for which the Fragment was created
// does not exist anymore.
// Also, cleanup: remove reference to Fragment from mItems
for(Map.Entry<Long, MainListFragment> entry : mItems.entrySet()) {
if(entry.getValue().equals(f)) {
mItems.remove(entry.getKey());
break;
}
}
// Let ViewPager remove the Fragment by returning POSITION_NONE.
return POSITION_NONE;
}
}
Ahora bien, si se elimina un elemento del conjunto de datos (this.dataset
) y llamar notifyDataSetChanged()
en la instancia de MyFragmentPagerAdapter
, eliminará el elemento de la ViewPager (incluso si es que se está viendo actualmente).
Digamos this.dataset
contiene 5 elementos y desea mover el n. ° 2 al final de la ViewPager. Para lograr esto, tendrá que posicionar el ítem n. ° 2 al final de su fuente de datos (ya sea a través del Collection.Sort
o de alguna otra manera). Te mostraré la manera fácil.
ArrayList<MyObject> list = new ArrayList<>();
MyFragmentPagerAdapter adapter = new MyFragmentPagerAdapter(list);
viewpager.setAdapter(adapter);
...
MyObject item = list.get(2);
list.remove(item);
list.add(item); // now it's positioned at the end of the list
adapter.notifyDataSetChanged(); // voilá, that should do the trick!
adapter.notifyDataSetChanged()
llama finalmente viewpager.dataSetChanged()
, que a su vez llama a adapter.getItemPosition(..)
en cada una de sus páginas. El resultado de esa llamada al método determina si y dónde aparecerá la página (Fragmento en este caso).
Muy comprensible. ¿Alguna razón por la que no está utilizando un FragmentStatePagerAdapter con esta implementación? ¿Sus listas de artículos harán que la clase a gran escala pierda todas las razones de su usabilidad? – jbenowitz
Esto tampoco pareció ayudarme. Estoy eliminando elementos, en total. Cada vez que fui al siguiente artículo, eliminé el elemento anterior, se deslizaría pero a mitad de deslizar cambiaría el siguiente ítem para que fuera el ítem después de eso. Visualmente: A, B, C elementos en el adaptador Vista A, deslice hacia B. Comience eliminando A, pase hacia la mitad B, Destello hacia C. – jbenowitz
Sí, esto es esperado. Si elimina A, B será pos == 0 y C pos == 1. Su elemento actual ('viewPager.setCurrentItem (int)') se establece en 1 al deslizar de A a B. Cuando elimina A, la posición actual seguirá siendo 1, lo que significa que 'ViewPager' saltará a C.Puede corregir esto estableciendo 'viewPager.setCurrentItem (adapter.getItemPosition (fragment-B))' cuando elimine A. – Reinier