2012-02-22 7 views
17

Mam ViewPager z trzema elementami. Próbuję ustawić ViewPager, aby wyświetlić stronę najbardziej na prawo (który byłby drugi element). Zwraca to wyjątek IndexOutOfBounds, choć wiem, że indeks powinien znajdować się w granicach. Oto dokładny stos:Android ViewPager rzuca wyjątek IndexOutOfBounds przy ustawianiu bieżącego elementu/strony

02-22 12:22:50.256: E/AndroidRuntime(384): FATAL EXCEPTION: main 
02-22 12:22:50.256: E/AndroidRuntime(384): java.lang.IndexOutOfBoundsException: index=1 count=0 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.view.ViewGroup.addInArray(ViewGroup.java:2050) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.view.ViewGroup.addViewInner(ViewGroup.java:1994) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.view.ViewGroup.addViewInLayout(ViewGroup.java:1958) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.view.ViewGroup.addViewInLayout(ViewGroup.java:1939) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.support.v4.view.ViewPager.addView(ViewPager.java:917) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.view.ViewGroup.addView(ViewGroup.java:1828) 
02-22 12:22:50.256: E/AndroidRuntime(384): at us.tagverse.pagertest.MasterActivity$PAdapter.instantiateItem(MasterActivity.java:518) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.support.v4.view.PagerAdapter.instantiateItem(PagerAdapter.java:110) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:649) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.support.v4.view.ViewPager.populate(ViewPager.java:783) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1016) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.view.View.measure(View.java:8313) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1017) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.widget.LinearLayout.measureVertical(LinearLayout.java:386) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.widget.LinearLayout.onMeasure(LinearLayout.java:309) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.view.View.measure(View.java:8313) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.widget.FrameLayout.onMeasure(FrameLayout.java:250) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.view.View.measure(View.java:8313) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.widget.FrameLayout.onMeasure(FrameLayout.java:250) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.view.View.measure(View.java:8313) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.view.ViewRoot.performTraversals(ViewRoot.java:839) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.view.ViewRoot.handleMessage(ViewRoot.java:1859) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.os.Handler.dispatchMessage(Handler.java:99) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.os.Looper.loop(Looper.java:123) 
02-22 12:22:50.256: E/AndroidRuntime(384): at android.app.ActivityThread.main(ActivityThread.java:3683) 
02-22 12:22:50.256: E/AndroidRuntime(384): at java.lang.reflect.Method.invokeNative(Native Method) 
02-22 12:22:50.256: E/AndroidRuntime(384): at java.lang.reflect.Method.invoke(Method.java:507) 
02-22 12:22:50.256: E/AndroidRuntime(384): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 
02-22 12:22:50.256: E/AndroidRuntime(384): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 
02-22 12:22:50.256: E/AndroidRuntime(384): at dalvik.system.NativeStart.main(Native Method) 

Należy pamiętać, że przyczyną jest java.lang.IndexOutOfBoundsException: index=1 count=0. Oznaczałoby to, że liczba stron/pozycji wynosi 0, a indeks, który żądam, to 1. Żadna z tych rzeczy nie jest prawdziwa. Oto jak wzywam moje ViewPager i prosząc podanej strony:

ViewPager pager = (ViewPager) findViewById(R.id.ma_viewcontainer); 
PAdapter adapter = new PAdapter(); 
pager.setAdapter(adapter); 
pager.setCurrentItem(2); 

Zauważ, że ta rozmowa nie daje żadnych błędów i poprawnie ustawia bieżący element do pozycji środkowej (indeks 1):

ViewPager pager = (ViewPager) findViewById(R.id.ma_viewcontainer); 
PAdapter adapter = new PAdapter(); 
pager.setAdapter(adapter); 
pager.setCurrentItem(1); 

Mam 3 pozycje w widoku pager. Oto moja pełna klasa PAdapter, która rozszerza klasę PagerAdapter:

private class PAdapter extends PagerAdapter implements TitleProvider { 

    private int COUNT = 3; 

    private static final int SETTINGS_ACTIVITY = 0; 
    private static final int MAIN_ACTIVITY = 1; 
    private static final int FRIEND_LIST_ACTIVITY = 2; 

    @Override 
    public int getCount() { 
     return COUNT; 
    } 

    @Override 
    public Object instantiateItem(View collection, int position) { 
     LinearLayout layout = new LinearLayout(getApplicationContext()); 
     LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     switch(position) { 
     case MAIN_ACTIVITY : 
      layout = (LinearLayout) inflater.inflate(R.layout.main, null, false); 
      initMainLayout(layout); 
      break; 
     case SETTINGS_ACTIVITY : 
      layout = (LinearLayout) inflater.inflate(R.layout.settings, null, false); 
      initSettingsLayout(layout); 
      break; 
     case FRIEND_LIST_ACTIVITY : 
      layout = (LinearLayout) inflater.inflate(R.layout.friend_list, null, false); 
      initFriendListLayout(layout); 
      break; 
     } 
     ((ViewPager)collection).addView(layout, position); 
     return layout; 
    } 

    @Override 
    public void destroyItem(View collection, int position, Object view) { 
     ((ViewPager)collection).removeView((LinearLayout)view); 
    } 

    @Override 
    public boolean isViewFromObject(View v, Object o) { 
     return v == (LinearLayout)o; 
    } 

    @Override 
    public void finishUpdate(View arg0) { 
     //no need 
    } 

    @Override 
    public void restoreState(Parcelable arg0, ClassLoader arg1) { 
     //no need 
    } 

    @Override 
    public Parcelable saveState() { 
     return null; 
    } 

    @Override 
    public void startUpdate(View arg0) { 
     //no need 
    } 

    @Override 
    public String getTitle(int position) { 
     Resources res = getApplicationContext().getResources(); 
     switch(position) { 
     case MAIN_ACTIVITY : 
      return res.getString(R.string.app_name); 
     case SETTINGS_ACTIVITY : 
      return res.getString(R.string.settings); 
     case FRIEND_LIST_ACTIVITY : 
      return res.getString(R.string.friend_list); 
     default : 
      return null; 
     } 
    } 
} 

Linia ((ViewPager)collection).addView(layout, position); powoduje awarię.

Jak widać, trzy elementy. Używanie setCurrentItem() z parametrem 0 lub 1 działa dobrze, ale 2 powoduje ten dziwny błąd. Nie mam pomysłów na rozwiązanie ... Niestety ViewPager znajduje się w niezbadanych wodach Androida. Jeśli ktokolwiek ma pewien wgląd w to, jak rozwiązać ten problem, będzie to bardzo cenne. Dzięki!

EDIT: Zgodnie z sugestią Shereef, w Próbowałem zalogowaniu liczyć dziecko poprzez collection.getChildCount() i mam następujący wynik:

02-22 15:20:42.274: E/children count(645): count: 0 
02-22 15:20:42.454: E/children count(645): count: 1 
02-22 15:20:42.594: E/children count(645): count: 2 

To jest ciekawe. To, co mi to mówi, to tworzenie pustego PagerAdaptera i dodawanie ich pojedynczo. instantiateItem() jest wywoływany 3 razy dla trzech widocznych widoków (środek, lewo i prawo). Więc dodałem poniższy fragment kodu wewnątrz metody instantiateItem():

if(((ViewPager)collection).getChildCount() == 2) { 
    ((ViewPager)collection).setCurrentItem(2); 
} 

tak tylko wtedy, gdy liczba jest ustalona będzie 2 będzie to ustawić stronę do 2 (jest to hacky rozwiązanie, które nie w pełni rozwiązać problem , ale warto było spróbować). Mam podobny stos błędów, który wskazywał najpierw na linię: ((ViewPager)collection).setCurrentItem(2);, a następnie ((ViewPager)collection).addView(layout, position);.

Mam nadzieję, że pomoże to w pewnym stopniu.

+0

jeśli (kolekcja (ViewPager)) .getChildCount() == 2) { (kolekcja (ViewPager)) .setCurrentItem (2); } oznacza to, że widok zostanie utworzony i wprowadzony do kolekcji tylko w takim przypadku, inne będą przerysowane od podstaw, w związku z tym stracisz optymalizację widoku strony, aby odtworzyć widoki, a nie przerysować je od podstaw. –

Odpowiedz

23

Nie sądzę, że można po prostu zrobić ((ViewPager)collection).addView(layout, position). To zależy od twojego limitu strony poza ekranem, który domyślnie wynosi 1, jak sądzę. Zakładam, że używasz tylko 3 widoków, więc możesz zrobić coś takiego jak viewPager.setOffscreenPageLimit(3); w swoim `onCreate (lub w dowolnym miejscu, w którym nawiązałeś połączenie), aby uniknąć każdego odświeżania widoku za każdym razem, gdy go opuścisz.

W kilku samouczkach zobaczysz, że ((ViewPager) collection).addView(view, 0); jest używane w instantiateItem(). W ciągu ostatnich kilku tygodni sporo pracowałem z ViewPagers, a użycie 0 jako pozycji - wszystko wydaje się działać dobrze.

+1

Zrobiłem to! Dziwne, że nie ustawiłeś metody addView() na rzeczywistą pozycję dziecka, ale nie będę tego kwestionował! – JMRboosties

+0

Zgadzam się, że to dziwne, ale tak działa ViewPager. Cieszę się, że twój problem został naprawiony teraz :) – aimango

+0

Dziwne, to także naprawiło mój problem! – Petro

7

Widzę dziennik awarii, widzę, że zawiesza się w instancji. I don "t wiedzieć, która linia dokładnie bo nie mam numery linii

ale gdybym był Zakłady człowiekiem, to założę się, że:

((ViewPager)collection).addView(layout, position); 

awarie dla próbuje dodać widok w pozycji 1 podczas gdy nie ma stron w kolekcji Może sprawdzić collection.getchildcount() (może nazwa metody jest błędna) i wstawić w max (pozycja, liczba)

i.e wymienić pozycji z:

count > position ? position : count 

Edycja:

((ViewPager)collection).addView(layout, ((ViewPager)collection).getChildCount() > position ? position : ((ViewPager)collection).getChildCount()) 

P.S. Delegowanie z mojego telefonu przepraszam za okropną formatowania

Proszę zauważyć

02-22 12:22:50.256: E/AndroidRuntime(384): at us.tagverse.pagertest.MasterActivity$PAdapter.instantiat 

MasterActivity.java:518 

Liczba na końcu linii skopiowane i dowiedzieć się, która linia jest wtedy i tylko wtedy będziesz wiedzieć, która linia dostał crash

EDIT: PS o twoim rozwiązaniu

Myślę, że twoje rozwiązanie ustawia tylko bieżący element po utworzeniu 3 stron przez instancję, ale moja linia sprawi, że zadziała, nawet jeśli nie zostaną utworzone instancje.

+0

Przepraszam, tak, zapomniałem sprecyzować. Ta linia faktycznie powoduje awarię. Zaktualizuję pytanie, aby to odzwierciedlić. – JMRboosties

+0

dodano poprawkę Myślę, że to by zadziałało, dobranoc na teraz –

+0

Wpadłem na to rozwiązanie i dałem mu szansę, zobacz moje oryginalne pytanie o wyniki. – JMRboosties

Powiązane problemy