2017-02-23 10 views
0

Ich habe ein seltsames Problem mit ViewPager, wenn ich versuche, mehrere pageChangleListeners hinzuzufügen. Ich habe mit einer ähnlichen Beschreibung für eine post/Frage versucht suchen, konnte aber nicht so finden wir hier gehen:Android ViewPager - mehrere pageChangeListener funktioniert nicht richtig

kurze Version: nur 1 onPageChangeListener für die erste Seite auslöst, aber für die zweite Seite mehrere Zuhörer sind auslösen.

lange version: in meiner app brauche ich jeden ViewPager mehrere OnPageChangeListeners zu haben. Obwohl ich in der Android-Dokumentation keine Bestätigung finden konnte, schlägt der Name der Funktion "addOnPageChangeListener" vor, dass mehrere Listener auf den gleichen ViewPager gesetzt werden können (vor allem, weil es früher " PageChangeListener" war) Sie änderten es in "hinzufügen PageChangeListener"). Nun habe ich einige Codes, der jedes Mal, wenn eine Seite ausgeführt werden muss in jedem ViewPager in meiner app ist so gewählt, machte ich meine eigenen ViewPager und OnPageChangeListener Klassen:

public class MyViewPager extends ViewPager 
{ 
    private ArrayList<Sequence> mSequenceList; 

    public MyViewPager(Context context) 
    { 
     super(context); 
    } 

    public MyViewPager(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 
    } 

    @Override 
    public void setAdapter(PagerAdapter adapter) 
    { 
     super.setAdapter(adapter); 

     mSequenceList = ((MyPagerAdapter)adapter).getSequences(); 

     addOnPageChangeListener(new MyOnPageChangedListener(mSequenceList)); 
     Log.i("aaaaa", "added listener from MyViewPager"); 
    } 
} 

und auch machte ich meine eigenen Seite ändern Hörer:

public class MyOnPageChangedListener implements MyViewPager.OnPageChangeListener 
{ 
    private static final String TAG = "MyOnPageChangedListener"; 

    private ArrayList<Sequence> sequenceList; 

    public MyOnPageChangedListener(ArrayList<Sequence> sequenceList) 
    { 
     this.sequenceList = sequenceList; 
    } 

    @Override 
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) 
    { 
     //do nothing 
    } 

    @Override 
    public void onPageSelected(int position) 
    { 
     Log.i("aaaaa", "selecting page " + position + " from my listener"); 

     //do something 
    } 

    @Override 
    public void onPageScrollStateChanged(int state) 
    { 
     //do nothing 
    } 

ich habe auch in meiner Tätigkeit des OnCreate:

mPageChangedListener = new ViewPager.OnPageChangeListener() 
     { 
      @Override 
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) 
      { 
       //do nothing 
      } 

      @Override 
      public void onPageSelected(int position) 
      {Log.i("aaaaa", "selecting page " + position + " from activity"); 
       //do something 
      } 

      @Override 
      public void onPageScrollStateChanged(int state) 
      { 
       //do nothing 
      } 
     }; 

     mViewPager.addOnPageChangeListener(mPageChangedListener); 
     Log.i("aaaaa", "added listener from activity"); 

und ich verwende diese in meiner Tätigkeit onPageSelected für die erste Seite zu triggern

@Override 
protected void onResume() 
{ 
    super.onResume(); 

    mViewPager.post(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
      mPageChangedListener.onPageSelected(mViewPager.getCurrentItem()); 
     } 
    }); 
} 

aber wenn ich die App laufen bekomme ich ein seltsames Verhalten. hier ist die Log-Ausgabe:

02-23 03:08:41.192 17147-17147/com.*** I/aaaaa: added listener from MyViewPager 
02-23 03:08:41.193 17147-17147/com.*** I/aaaaa: added listener from activity 
02-23 03:08:41.273 17147-17147/com.*** I/aaaaa: selecting page 0 from activity 
02-23 03:09:03.609 17147-17147/com.*** I/aaaaa: selecting page 1 from my listener 
02-23 03:09:03.609 17147-17147/com.*** I/aaaaa: selecting page 1 from activity 

, wie Sie beiden Zuhörer sehen können hinzugefügt, aber für die erste Seite (Index 0) nur der Hörer aus der Aktivität ausgelöst wird, während für die zweite Seite (Index 1) beiden Hörer werden ausgelöst.

Dies ist ein großes Problem für mich als meine eigene OnPageChangedListener muss für jede einzelne Seite ausgelöst werden.

weiß jemand, warum das passiert und wie es zu beheben?

Antwort

0

natürlich 1 Minute nach dem Posten dieser Frage habe ich es herausgefunden ...Ich poste die Lösung für jeden, der einem ähnlichen Problem gegenübersteht:

Das Problem liegt in der onResume() - Methode meiner Aktivität. Mir ist aufgefallen, dass ich nur den Hörer aktiviere, den ich in der Aktivität registriert habe, und nicht meinen eigenen Zuhörer. Problem ist, dass ich keinen Zugriff auf MyOnPageChangedListener von der Aktivität so was ich es eine globale Variable in MyOnPageChangedListener und eine get-Methode, um darauf zuzugreifen. hier ist meine modifizierte Klasse:

public class MyViewPager extends ViewPager 

{ 
    private ArrayList<Sequence> mSequenceList; 

    private MyOnPageChangedListener mPageChangeListener; 

    //making the compiler happy 
    public MyViewPager(Context context) 
    { 
     super(context); 
    } 

    //making the compiler happy 
    public MyViewPager(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 
    } 

    @Override 
    public void setAdapter(PagerAdapter adapter) 
    { 
     super.setAdapter(adapter); 

     mSequenceList = ((MyPagerAdapter)adapter).getSequences(); 

     mPageChangeListener = new MyOnPageChangedListener(mSequenceList); 
     addOnPageChangeListener(mPageChangeListener); 
     Log.i("aaaaa", "added listener from MyViewPager"); 
    } 

    public MyOnPageChangedListener getMyPageChangeListener() 
    { 
     return mPageChangeListener; 
    } 
} 

und hier ist meine aktualisiert onResume:

@Override 
protected void onResume() 
{ 
    super.onResume(); 

    invalidateOptionsMenu(); 

    //this is to invoke "onPageSelected()" for the first page 
    //when the viewpager is first created, and when the activity is resumed 
    //(for example when coming back from "edit profile") 
    mViewPager.post(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
      mViewPager.getMyPageChangeListener() 
         .onPageSelected(mViewPager.getCurrentItem()); 
      mPageChangedListener.onPageSelected(mViewPager.getCurrentItem()); 
     } 
    }); 
} 

aber dies wie ein Hack ein wenig fühlt sich für mich wie zu einer eleganten Lösung im Gegensatz ... auch bedeutet dies, dass Ich muss dies manuell für jede Aktivität tun, wo ich meinen eigenen Listener auslösen möchte.

Leider gibt es keine solche Methode "getAllPageChangedListeners".

Gibt es eine bessere Lösung?

0

Da Sie onPageSelected() explizit nur auf Ihrem mPageChangedListener aufrufen, durchläuft es nicht den gesamten Zyklus zum Auswählen einer Seite und ruft damit nicht onPageSelected() für alle zugewiesenen Listener auf. Wenn Sie die ViewPager Quelle schauen, können Sie sehen, dass dispatchOnPageSelected (int position) wird nicht, wenn Sie

mPageChangedListener.onPageSelected(mViewPager.getCurrentItem()); 

wie Sie haben auslösen aufgerufen werden.

Ich verpasste die Tatsache, dass setCurrentItem (int position) keine Wirkung hat, wenn das ausgewählte Element bereits ausgewählt ist ... so für die anfängliche Auswahl sollten Sie eine Instanz aller Listener behalten und onPageSelected() aufrufen. Danach wird die Verwendung von mViewPager.setCurrentItem (int position) beide (oder alle) Ihre Listener auslösen.

+0

Ja, ich bemerkte das auch fast sofort nach dem Posten der Frage lol (siehe meine Antwort). Leider, während Ihre Lösung ** sollte ** funktionieren, tut es nicht: wenn ich "setCurrentItem (mViewPager.getCurrentItem())" aufrufen, löst es nicht die "onPageSelected" -Methode (in einem der Listener) aus. –

+0

Richtig, ich habe verpasst, dass das ausgewählte Element standardmäßig 0 ist. Die erneute Auswahl hat also keine Auswirkungen. Bearbeitete die Antwort, die Lösung ist so ziemlich deine eigene Antwort :) –

Verwandte Themen