2012-02-22 4 views
17

Ho un ViewPager con tre elementi. Sto cercando di impostare ViewPager per visualizzare la pagina più a destra (che sarebbe il 2 ° elemento). Questo sta restituendo un'eccezione IndexOutOfBounds, anche se so che l'indice dovrebbe essere in limiti. Qui è lo stack esatto:ViewPager Android che lancia l'eccezione IndexOutOfBounds quando si imposta l'elemento/pagina corrente

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) 

Nota che la causa è java.lang.IndexOutOfBoundsException: index=1 count=0. Ciò implicherebbe che il conteggio delle pagine/elementi sia 0 e l'indice che sto richiedendo sia 1. Nessuna di queste cose è vera. Ecco come io chiamo il mio ViewPager e richiede la pagina data:

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

Si noti che questa chiamata non dà alcun errore, e imposta correttamente l'elemento corrente alla voce di mezzo (indice 1):

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

Ho un conteggio di 3 elementi nel pager della vista. Qui è la mia classe PAdapter pieno, che estende la classe 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; 
     } 
    } 
} 

La linea ((ViewPager)collection).addView(layout, position); causa l'arresto.

Come potete vedere, tre elementi. L'utilizzo di setCurrentItem() con un parametro 0 o 1 funziona bene, ma 2 causa questo strano errore. Ho esaurito le idee per risolverlo ... sfortunatamente ViewPager risiede in alcune acque inesplorate di Android a quanto pare. Se qualcuno ha qualche idea su come risolvere questo sarebbe molto apprezzato. Grazie!

EDIT: Come da suggerimento di Shereef, ho provato registrando contare il bambino via collection.getChildCount() e ha ottenuto il seguente risultato:

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 

Questo è interessante. Ciò che questo mi dice è che sta creando un PagerAdapter vuoto e aggiungendoli uno alla volta. instantiateItem() viene chiamato 3 volte per le tre viste visibili (centro, sinistra e destra). Così ho aggiunto questo blocco di codice all'interno del metodo instantiateItem():

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

Quindi, solo se il conteggio è stabilita per essere 2 sarà vero impostare la pagina 2 (questa è una soluzione hacky che non affrontare pienamente il problema , ma valeva la pena provare). Ho ottenuto uno stack di errore simile che indicava prima la riga: ((ViewPager)collection).setCurrentItem(2);, quindi ((ViewPager)collection).addView(layout, position);.

Spero che questo aiuti a dare qualche idea.

+0

if ((raccolta (ViewPager)) .getChildCount() == 2) { (raccolta (ViewPager)) .setCurrentItem (2); } questo significa che la vista verrà creata e inserita nella raccolta solo in tal caso, altri saperi verranno ridisegnati da zero, quindi si perde l'ottimizzazione del viewpager per riciclare le viste anziché ridisegnarle da zero –

risposta

23

Non penso che si possa fare solo ((ViewPager)collection).addView(layout, position). Dipende dal limite della pagina fuori dallo schermo, che per impostazione predefinita è 1, credo. Suppongo tu stia usando solo 3 visualizzazioni, quindi puoi fare qualcosa come viewPager.setOffscreenPageLimit(3); nel tuo `onCreate (o ovunque tu abbia effettuato la chiamata) per evitare che ogni vista venga aggiornata ogni volta che la lasci.

Vedrete in alcuni tutorial che ((ViewPager) collection).addView(view, 0); viene utilizzato in instantiateItem(). Ho lavorato un bel po 'con lo ViewPagers nelle ultime settimane, e usando 0 come posizione - tutto - il tempo sembra funzionare bene.

+1

Questo lo ha fatto! Strano che non si imposti il ​​metodo addView() sulla posizione effettiva del bambino, ma non lo metto in dubbio! – JMRboosties

+0

Sono d'accordo che è strano, ma è proprio come funziona ViewPager. Sono contento che il problema ora sia risolto :) – aimango

+0

Così strano, questo ha risolto anche il mio problema! – Petro

7

Vedo il registro di arresto anomalo. Vedo che si blocca in modo istanziato. I don "t so che la linea proprio perché non ho i tuoi numeri di riga

Ma se fossi un uomo di scommesse, sono pronto a scommettere che:

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

si blocca per aver tentato di aggiungere alla posizione vista 1 mentre non ci sono pagine nella collezione Forse controllare il collection.getchildcount() (forse il nome del metodo è sbagliato) e inserire al massimo (posizione, contare)

i.e sostituire posizione:

count > position ? position : count 

EDIT:

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

P.S. Distacco dal mio telefono dispiaciuto per la formattazione orribile

Si prega di notare

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

MasterActivity.java:518 

Il numero alla fine della linea ho copiato e scoprire quale linea è allora e solo allora si saprà quale linea ha ottenuto il crash

MODIFICA: PS sulla tua soluzione

Penso che la tua soluzione imposta la voce corrente solo dopo che le 3 pagine sono state istanziate da un elemento istanziato, ma la mia linea avrebbe funzionato anche se non sono state istanziate.

+0

Spiacente, sì, ho dimenticato di specificare. Quella linea infatti causa l'incidente. Aggiornerò la domanda per riflettere questo – JMRboosties

+0

ha aggiunto la correzione penso che avrebbe funzionato, buonanotte per ora –

+0

Mi è venuta in mente questa soluzione e l'ho provata, vedere la mia domanda originale per i risultati. – JMRboosties

Problemi correlati