Вопрос по android, android-viewpager – onPageSelected не срабатывает при вызове setCurrentItem (0)

57

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

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

Я установил начальную точку следующим образом:

 mPager.setCurrentItem(index);

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

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

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

Ваш Ответ

10   ответов
0
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.
        }
0

ViewPager и позвоните Слушателю самостоятельно, когда позиция изменится с 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);
        }

}
Это действительно близко к ответу, но дочерний фрагмент еще не был присоединен, поэтому, если вы попытаетесь вызвать getParentFragment или getActivity, произойдет сбой. Где-нибудь еще это можно сделать, чтобы гарантировать, что фрагмент был прикреплен?
кто говорит об активности и фрагментах в этом ответе?
76

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

onPageChangeListener.onPageSelected(viewPager.getCurrentItem());

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

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

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

Работает как шарм.
Отлично. Наконец-то я нашел этот ответ
размещение исполняемого файла - это просто секретный соус, который мне был нужен, чтобы убедиться, что представления viewPager уже созданы, прежде чем инициировать вызов onPageSelected. Ницца!
безусловно, правильный ответ
-1

в методе onViewCreated вызовите mPager.setOnPageChangeListener (this)

-4

pager.setCurrentItem(1);
pager.setCurrentItem(0);
А если у вашего пейджера есть только один элемент ...?
0

    viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

        @Override
        public void onPageScrollStateChanged(int state) {}

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

        @Override
        public void onPageSelected(int position) {
            onPage(position);
        }
    });

    // call first time
    onPage(0); 

    private void onPage(int position) {
        //...
    }
23

Я проверил исходный код 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 будет ложным, поэтому onPageSelected () не будет отправлено.

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

How to solve this problem:

Copy the code of ViewPager to your own project and fix it:

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

then use your own ViewPager.

Since you consciously called setCurrentItem(0) and have a refrence to the OnPageChangedListener, dispatch the onPageSelected() by yourself.

听楼下怎么说...

Хорошая находка. Вы сообщили об этом как о проблеме?
Есть ли способ сделать это без копирования кода? Есть ли способ исправить это в подклассе?
это говорит, что PagerAdapter.DataSetObserver не может быть разрешен к типу?
А вот ссылка на исходный код:grepcode.com/file/repository.grepcode.com/java/ext/…
0

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

Ну, это срабатывает для страницы, которая открывается первой, то есть если страница не первая. Я знаю, это звучит странно, но это причина моего вопроса. jpihl
Запуск "onPageSelected ()" может привести к NullPointer!
33

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

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

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

А потом сразу после звонка

setCurrentItem(index);

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

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

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

@Defuera, я не понимаю твою озабоченность. Не могли бы вы уточнить, или, возможно, представить лучшее решение? jpihl
На самом деле это плохо, так как OnPageChangeListener вызывается после некоторой асинхронной работы, и с этим «трюком» у вас не будет правильной работы во многих случаях
И если я хочу прослушать изменение страницы на самом ферменте, что я могу сделать?
Хороший .. Мне нравится твой трюк ... +1 голос с моей стороны :)
лучшее решение - вызвать setCurrentItem (index); inside view.post (new Runnable () {setCurrentItem (index);}); этот код гарантирует, что OnPageChangeListener будет вызван. по крайней мере, в моих случаях
1

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

Похожие вопросы