2017-02-23 4 views
0

У меня есть странная проблема с ViewPager, когда я пытаюсь добавить несколько pageChangleListeners. Я попытался ищет пост/вопрос с подобным описанием, но не мог найти так что здесь мы идем:Android ViewPager - несколько pageChangeListener не работает должным образом

короткая версия: только 1 onPageChangeListener является запуск для первой страницы, но на второй странице несколько слушателей запуск.

длинная версия: В моем приложении мне нужно, чтобы каждый ViewPager имел несколько OnPageChangeListeners. даже несмотря на то, что я не смог найти подтверждения в документации по Android, имя функции «addOnPageChangeListener» предполагает, что я могу настроить несколько слушателей на один и тот же ViewPager (особенно потому, что он был «set PageChangeListener» и они изменили его на "добавить PageChangeListener"). Теперь у меня есть некоторый код, который должен выполняться каждый раз, когда страница выбирается в любом ViewPager в моем приложении, так что я сделал свои собственные ViewPager и OnPageChangeListener классов:

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"); 
    } 
} 

, а также я сделал свой собственное изменение страницы слушателя:

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 
    } 

я также это в 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"); 

и я использую это в моей деятельности, чтобы вызвать onPageSelected для первой страницы

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

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

но когда я запускаю приложение, я получаю странное поведение. вот выход журнала:

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 

, как вы можете видеть, как слушатели будут добавлены, но для первой страницы (индекс 0) только слушатель от активности запускаются в то время как для второй страницы (индекс 1) оба слушателей запускаются.

Это серьезная проблема для меня, так как мой собственный onPageChangedListener должен запускаться для каждой отдельной страницы.

Кто-нибудь знает, почему это происходит и как это исправить?

ответ

0

конечно через 1 минуту после размещения этого вопроса я понял это ...Я отправляю решение всем, кто может столкнуться с аналогичной проблемой:

проблема заключается в методе onResume() моей деятельности. я заметил, что я только запускаю прослушиватель, который я зарегистрировал в своей деятельности, а не мой пользовательский прослушиватель. проблема в том, что у меня нет доступа к MyOnPageChangedListenerот активности, поэтому я сделал ее глобальной переменной в MyOnPageChangedListener и добавил метод get для доступа к ней. вот мой модифицированный класс:

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; 
    } 
} 

и вот мой обновленный 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()); 
     } 
    }); 
} 

однако это чувствует себя немного как взломать ко мне в противоположность элегантное решение ... и это означает, что Я должен сделать это вручную для каждого вида деятельности, где я хочу запустить свой собственный слушатель.

К сожалению, такого метода нет «getAllPageChangedListeners».

есть ли лучшее решение?

0

Поскольку вы вызываете onPageSelected() явно только на ваш mPageChangedListener, он не проходит полный цикл выбора страницы, поэтому не вызывает onPageSelected() для всех назначенных слушателей. Если вы посмотрите на исходный код ViewPager, вы можете увидеть, что dispatchOnPageSelected (целое положение) обыкновение быть вызван, если вы вызываете

mPageChangedListener.onPageSelected(mViewPager.getCurrentItem()); 

, как вы делали.

Я пропустил тот факт, что setCurrentItem (int position) не действует, если выбранный элемент уже выбран ... поэтому для первоначального выбора вы должны сохранить экземпляр всех своих слушателей и вызвать onPageSelected() для каждого. После этого использование mViewPager.setCurrentItem (int position) вызовет как (или все) ваших слушателей.

+0

Да, я заметил, что слишком почти сразу после публикации вопроса LOL (см. Мой ответ). к сожалению, пока ваше решение ** должно работать **, это не так: когда я вызываю «setCurrentItem (mViewPager.getCurrentItem())», он не вызывает метод onPageSelected (в любом из слушателей). –

+0

Правильно, я пропустил, что по умолчанию выбранный элемент равен 0, поэтому его выбор снова не влияет. Отредактированный ответ, решение в значительной степени ваш собственный ответ :) –

Смежные вопросы