Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

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

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

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

setCurrentItem(index);

в Activity, добавьте следующую инструкцию if

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

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

Ответ 2

Самое чистое решение, которое я нашел для этого до сих пор, - это сделать ссылку на 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.

Ответ 3

На самом деле я думаю, что это BUG. Я проверил исходный код 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...) не является.

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

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

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

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

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

  • 听 ​​楼下 怎么 说...

Ответ 4

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

Ответ 5

Кажется, что для меня работает следующее решение. т.е. я получаю обратный вызов в позиции 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) {}
        });

Ответ 6

Вы можете расширить 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);
        }

}

Ответ 7

public class PageChangeListener implements ViewPager.OnPageChangeListener {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        if (state == ViewPager.SCROLL_STATE_IDLE && getCurrentItem() == 0) {
         //this indicate viewpager finish scroll and page at position 0 is selected.
        }

Ответ 8

если вам не нужна анимация экрана, попробуйте

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