Tak. Postaram się odpowiedzieć na twoją sprawę, pokazując, jak to zrobiłem, a ja pokażę przykład Twojej sprawy poniżej mojej próbki kodu.
Zasadniczo, aby to osiągnąć, musisz śledzić, jaką pozycję mają Twoje Fragmenty. Poniżej znajduje się implementacja zastosowana dla mojego FragmentPagerAdapter
, która wykorzystuje ArrayList jako źródło danych.
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;
}
}
Teraz jeśli usunąć element z zestawu danych (this.dataset
) i wywołać notifyDataSetChanged()
na wystąpienie MyFragmentPagerAdapter
będzie usunąć element z ViewPager (nawet jeśli jest aktualnie oglądany).
Załóżmy, że this.dataset
zawiera 5 elementów, i chcesz przenieść # 2 na koniec ViewPager. Aby to osiągnąć, musisz umieścić pozycję # 2 na końcu źródła danych (przez Collection.Sort
lub w inny sposób). Po prostu pokażę ci łatwą drogę.
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()
ostatecznie nazywa viewpager.dataSetChanged()
, co z kolei wywołuje adapter.getItemPosition(..)
na każdej z jej stron. Wynik tego wywołania metody określa, czy i gdzie pojawi się strona (fragment w tym przypadku).
Bardzo zrozumiały. Każdy powód, dla którego nie używasz FragmentStatePagerAdapter z tej implementacji? Czy twoja lista mItems sprawi, że klasa na dużą skalę straci wszystkie powody jej użyteczności? – jbenowitz
To również mi nie pomogło. Usuwam wszystkie przedmioty. Ilekroć poszedłem do następnego przedmiotu, usunąłem poprzedni element, to przesuwałbym, ale w połowie machnięcia zmieniałem następny przedmiot, by był po nim. Wizualnie: A, B, C elementy w adapterze Widok A, Przesuń do B. Rozpocznij usuwanie A, przesuń w połowie do B, Flash do C. – jbenowitz
Tak, to jest oczekiwane. Jeśli usuniesz A, B będzie pos == 0, a C pos == 1. Twój bieżący element ('viewPager.setCurrentItem (int)') jest ustawiony na 1 podczas przesuwania z A do B. Kiedy usuniesz A, aktualna pozycja będzie nadal wynosić 1, co oznacza, że 'ViewPager' przeskoczy do C.Możesz to poprawić, ustawiając 'viewPager.setCurrentItem (adapter.getItemPosition (fragment-B))' po usunięciu A. – Reinier