Вопрос по android, android-viewpager – onPageSelected не срабатывает при вызове setCurrentItem (0)
У меня есть активность с ViewPager, который отображает кучу картинок. Когда он запускается, позиция ViewPager устанавливается на основе того, что пользователь выбрал в предыдущем действии. Похоже на галерею.
Я хочу, чтобы onPageSelected вызывалось каждый раз, когда выбирается новая страница, т. Е. При первом открытии действия или при переходе пользователя на новую страницу.
Я установил начальную точку следующим образом:
mPager.setCurrentItem(index);
Все работает, за исключением случаев, когда setCurrentItem вызывается с индексом, установленным в 0, так как это не сработает onPageSelected.
mPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int index) {
Log.d(TAG, "onPageSelected " + index);
}
...
}
Итак, мой вопрос: это ошибка, и если да, что я могу с этим поделать?
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.
}
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);
}
}
которое я до сих пор нашел для этого, - это взять ссылку на 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.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) {
//...
}
Я проверил исходный код 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.
听楼下怎么说...
onPageSelected
не запускается для страницы, которая открывается первой. Для этого случая я вручную выполняю все необходимые действия. Кроме того, я полагаю, что призыв кonPageSelected(0)
должно работать тоже.
я не смог выяснить, является ли это ошибкой (или функцией). Но я подумала, что поделюсь, как может выглядеть возможное решение проблемы.
Напишите функциональность, которую вы хотите выполнить в методе в Activity, а затем вызовите ее в методе onPageSelected.
mPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int index) {
myOnPageSelectedLogic(index);
}
...
}
А потом сразу после звонка
setCurrentItem(index);
в Activity добавьте следующий оператор if
if(index == 0) {
myOnPageSelectedLogic(0);
}
Это не очень красиво, но я надеюсь, что это кому-то поможет :)
кажется, работает для меня. то есть я получаю обратный вызов в позиции 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) {}
});