OnPageSelected не запускается при вызове setCurrentItem (0)

У меня есть Activity с ViewPager, который отображает кучу изображений. Когда он начинается, позиция ViewPager устанавливается на основе того, что пользователь выбрал в предыдущем действии. Подобно галерее.

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

Я установил начальную точку так:

mPager.setCurrentItem(index); 

Все работает, за исключением случаев, когда setCurrentItem вызывается с индексом, установленным в 0, поскольку это не будет вызывать onPageSelected.

 mPager.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int index) { Log.d(TAG, "onPageSelected " + index); } ... } 

Поэтому мой вопрос: Это ошибка, и если да, то что я могу с этим поделать?

Самое чистое решение, которое я нашел для этого до сих пор, – это сделать ссылку на onPageChangeListener, которую вы установили на ViewPager (так как я не думаю, что есть метод ViewPager.getOnPageChangeListener ()), после того как вы установили адаптер ViewPager , вызов:

 onPageChangeListener.onPageSelected(viewPager.getCurrentItem()); 

Тем не менее, фрагмент для страницы в текущем индексе еще не был создан (по крайней мере, если вы используете FragmentStatePagerAdapter), поэтому вам может понадобиться обернуть его в runnable, ala:

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

Кроме того, если внутри обработчика onPageSelected вам нужна ссылка на фрагмент, вам придется сделать это самостоятельно. Я использую абстрактный базовый класс для моего FragmentStatePagerAdapter, который переопределяет методы создания и уничтожения и добавляет / удаляет фрагменты из SparseArray.

Хорошо, поэтому я не смог выяснить, является ли это ошибкой (или функцией). Но я подумал, что поделился бы тем, как может выглядеть возможное решение проблемы.

Напишите функции, которые вы хотите выполнить в методе в Activity, а затем вызовите это в методе onPageSelected.

 mPager.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int index) { myOnPageSelectedLogic(index); } ... } 

И затем сразу после вызова

 setCurrentItem(index); 

В Управлении добавьте следующий оператор if

 if(index == 0) { myOnPageSelectedLogic(0); } 

Это не супер красиво, но я надеюсь, что это поможет кому-то 🙂

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

 if (dispatchSelected && mOnPageChangeListener != null) { mOnPageChangeListener.onPageSelected(item); } 

Выше, переменная dispatchSelected определяется кодом:

 final boolean dispatchSelected = mCurItem != item; //item is what you passed to setCurrentItem(item) 

И переменная mCurItem определяется и инициализируется как:

 private int mCurItem; // Index of currently displayed page. 

Таким образом, mCurItem по умолчанию равен 0. При вызове setCurrentItem (0) dispatchSelected будет false, поэтому onPageSelected () не будет отправлен.

Теперь мы должны понять, почему вызов setCurrentItem (0) является проблемой, а setCurrentItem (1, или 2, 3 …) – нет.

Как решить эту проблему:

  1. Скопируйте код ViewPager в свой собственный проект и исправьте его:

     from final boolean dispatchSelected = mCurItem != item; //the old line to final boolean dispatchSelected = mCurItem != item || mFirstLayout; //the new line 

    Затем используйте свой собственный ViewPager.

  2. Поскольку вы сознательно называете setCurrentItem (0) и имеете ссылку на OnPageChangedListener, отправьте onPageSelected () самостоятельно.

  3. 听 楼下 怎么 说 …

onPageSelected не запускается для первой страницы. В этом случае я вручную выполняю все необходимые действия. Кроме того, я полагаю, что вызов onPageSelected(0) тоже должен работать.

Для меня, похоже, работает следующее решение. Т.е. я получаю обратный вызов в позиции 0 при первом загрузке viewpager и для всех последующих выборов либо из прокрутки пользователя, либо из вызова setCurrentItem (x). Я не наблюдал никакого нежелательного поведения.

 viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { if (positionOffsetPixels == 0) { //Do something on selected page at position } } @Override public void onPageSelected(int position) {} @Override public void onPageScrollStateChanged(int state) {} }); 

Вы можете расширить ViewPager и вызвать Listener самостоятельно, когда позиция изменится с 0 на 0

 public class BetterViewPager extends ViewPager { public BetterViewPager(Context context, AttributeSet attrs) { super(context, attrs); } // we some the listner protected OnPageChangeListener listener; @Override public void setOnPageChangeListener(OnPageChangeListener listener) { super.setOnPageChangeListener(listener); this.listener = listener; } @Override public void setCurrentItem(int item) { // when you pass set current item to 0, // the listener won't be called so we call it on our own boolean invokeMeLater = false; if(super.getCurrentItem() == 0 && item == 0) invokeMeLater = true; super.setCurrentItem(item); if(invokeMeLater && listener != null) listener.onPageSelected(0); } } 

Если вам не нравится анимация экрана

 pager.setCurrentItem(1); pager.setCurrentItem(0);