2012-09-07 7 views

Odpowiedz

31

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).

+1

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

+0

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

+0

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

1

Właśnie czytałem o tym wszystkim.

Zwykłym sposobem korzystania z ViewPager jest posiadanie klasy PagerAdapter, która podaje ją we właściwym miejscu we właściwym momencie. Istnieją ładne podklasy PagerAdapter, FragmentPagerAdapter i FragmentStatePagerAdapter, które są łatwiejsze w użyciu.

Jednak aby móc zmienić kolejność stron, musisz napisać własną podklasę PagerAdapter. Zasadniczo istnieją dwa sposoby, w jakie ViewPager wie, na której stronie się znajdujesz: numer strony i kluczowy obiekt, który podał mu adapter. W związku z tym powinieneś być w stanie zmienić kolejność bez utraty ViewPager.

Szczegóły na temat tego, jak to zrobić, znajdują się na this page. Jeszcze nie próbowałem, ale zrobię to w nadchodzących tygodniach. Myślę, że ta strona nie mówi wszystkiego. Nie ma wzmianki o metodzie getItem(), którą musi posiadać większość klas adaptera. Tak naprawdę nie widzę jeszcze, jak strony zostaną dodane do ViewPagera.

Czas znaleźć i przeczytać przykładowy kod.

Powiązane problemy