OnPageSelected не работает для первой страницы

Мой адаптер пейджера (расширяет PagerAdepter) имеет в нем текстовое представление. И я обновляю этот текст с помощью MainActivity onPageSelected. Его текстовое представление обновления для позиции > 0, но стартовая страница (позиция 0) не обновляется при запуске. Когда я прокручиваю вперед, а затем откидываюсь назад; он устанавливает значение для позиции 0, но я не мог установить значение ON START. Как установить значение для звездной страницы?

public void onPageSelected(int position) {

             switch (position) {
                case 0: 

                     PagerAdapter.tv.setText("value"); // => doesnt work on start

                    break;

                            default:
                                   PagerAdapter.tv.setText("value");
                                         break;
}
}

Полный код:

public class QuizStart extends SlidingFragmentActivity {
 @Override
        protected void onCreate(final Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

           this.setContentView(R.layout.activity_main);

              mPager = (ViewPager)findViewById(R.id.pager);         
            QuestionPagerAdapter mAdapter = new QuestionPagerAdapter();

            mPager.setAdapter(mAdapter);
            QuizStart.onPageSelected(0);

         mPager.setOnPageChangeListener(new OnPageChangeListener() {


            @Override
            public void onPageScrollStateChanged(int arg0) { }

            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) { }

            @Override
            public void onPageSelected(int position) {

             switch (position) {
                case 0: 

                     PagerAdapter.tv.setText("value"); // => doesnt work on start

                    break;

                            default:
                                   PagerAdapter.tv.setText("value");
                                         break;
                }
            }

        });
}
}

Ответ 1

Вы можете вручную вызвать onPageSelected(0) при создании OnPageChangeListener, чтобы установить начальное состояние:

OnPageChangeListener pageChangeListener = new OnPageChangeListener() {
    @Override
    public void onPageScrollStateChanged(int arg0) { }

    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) { }

    @Override
    public void onPageSelected(int position) {

        switch (position) {
        case 0: 
            QuizStart.next.setText(getmycurrentpage()+"");
            break;

        default:

            QuizStart.next.setText(getmycurrentpage()+"");
            break;
        }
    }
});

   mPager.setOnPageChangeListener(pageChangeListener);
   // do this in a runnable to make sure the viewPager views are already instantiated before triggering the onPageSelected call
   mPager.post(new Runnable()
   {
       @Override
       public void run() 
       {
           pageChangeListener .onPageSelected(viewPager.getCurrentItem());
       }
   });

Изменить

Теперь он не получит Null Pointer exception, как указано @metemet06

Ответ 2

Для меня следующий код

    viewPager.addOnPageChangeListener(myOnPageChangeListener);

.

    ViewPager.OnPageChangeListener myOnPageChangeListener = new ViewPager.OnPageChangeListener() {

    //declare key
    Boolean first = true;

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        if (first && positionOffset == 0 && positionOffsetPixels == 0){
            onPageSelected(0);
            first = false;
        }
    }

    @Override
    public void onPageSelected(int position) {
        //do what need
    }

    @Override
    public void onPageScrollStateChanged(int state) {
    }
};

Ответ 3

Моим решением было расширить адаптер пейджера и создать в нем интерфейс. Затем сделайте адаптер, чтобы вызвать интерфейс только один раз после создания адаптера. Внутри обратного вызова интерфейса вы можете вызывать метод onPageChanged без использования исключения nullpointer. Добавьте этот класс в свой проект и увеличьте его адаптер. Не забудьте установить прослушиватель для адаптера, прежде чем устанавливать адаптер на просмотрщик. Класс адаптера ниже:

public abstract class ExtendedPagerAdapter extends FragmentPagerAdapter {

private boolean instantiated;
private AdapterListener adapterListener;

public interface AdapterListener {
    void onAdapterInstantiated();
}

public ExtendedPagerAdapter(FragmentManager fragmentManager) {
    this(fragmentManager, null);
}

public ExtendedPagerAdapter(FragmentManager fragmentManager, AdapterListener adapterListener) {
    super(fragmentManager);
    this.adapterListener = adapterListener;
    instantiated = false;
}

@Override
public void finishUpdate(ViewGroup container) {
    super.finishUpdate(container);
    if (!instantiated) {
        instantiated = true;
        if (adapterListener != null) {
            adapterListener.onAdapterInstantiated();
        }
    }
}

public void setAdapterInstantiatedListener(AdapterListener adapterListener) {
    this.adapterListener = adapterListener;
}
}

Ответ 4

Я исправил проблему в своем приложении, добавив код, который должен быть выполнен для первой страницы в методе onCreate() моей активности.

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

Вызов onPageSelected() вручную вызвал NullPointerExceptions, просто das, описанный в других комментариях выше.

Ответ 5

Мне кажется, что то, что вы действительно хотите сделать, - это переопределение getPageTitle(), а затем где-то еще, захват этого заголовка страницы и установите его как текст TextView.

Таким образом, когда вы инициализируете свою активность, инициализируйте PagerAdapter и вызовите getTitle(0). Это даст вам название для страницы 0. Теперь установите это в текстовом представлении Activity. Позже, всякий раз, когда вы меняете страницы, просто вызывайте getTitle(newPosition) и обновляйте TextView.

Ответ 6

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

Вместо вызова функции OnPageSelected вручную, когда страница загружается в первый раз, скорее создайте пользовательский интерфейс шаг за шагом "обычный". Позже, когда пользователь меняет страницу, набор данных должен быть завершен, и он сохраняет, чтобы обновление было сделано в функции OnPageSelected.

Ответ 7

Поскольку я сделал то, что предлагалось здесь, и это не сработало, я опубликую то, что для меня работало, добавляло функцию создания экземпляров в onPageScrolled, например:

   @Override
   public void onPageScrolled(int arg0, float arg1, int arg2) {

           adapter.closeText(arg0, viewPager);

    }

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

Ответ 8

Этот код работает для меня. Сначала инициализируйте прослушиватель страницы. После setCurrentItem.

viewPager.setAdapter(adapter);
      viewPager.setOffscreenPageLimit(1);

      final ViewPager.OnPageChangeListener listener = new ViewPager.OnPageChangeListener() {
         @Override
         public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
         }

         @Override
         public void onPageSelected(int position) {

         }

         @Override
         public void onPageScrollStateChanged(int state) {
         }
      };
      viewPager.addOnPageChangeListener(listener);
      viewPager.setCurrentItem(position);

Ответ 9

На самом деле я нашел хороший способ, основанный на этом .

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

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

private boolean mFirstPageCalled = false;

Затем в слушателе:

@Override
public void onPageSelected(int position) {

    if(mFirstPageCalled) {
        // Do your thing
    } else {
        mFirstPageCalled = true;
    }
}

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

    mViewPager.post(new Runnable(){
        @Override
        public void run() {
            // Do your thing
        }
    });

В моем случае я просто перезвоню, здесь показан текущий фрагмент и работает над ним:

Fragment currentFragment = mPagerAdapter.instantiateItem(mViewPager, mViewPager.getCurrentItem());
currentFragment.customAction();

Метод post вызывается только один раз, поэтому он идеально подходит для обработки первой страницы.

Ответ 10

Мое решение - это расширенный ViewPager

class MyViewPager extends ViewPager {

    private List<OnPageChangeListener> _Listeners = new ArrayList<>();

    public MyViewPager(Context context) {
        super(context);
    }

    public MyViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void addOnPageChangeListener(OnPageChangeListener listener) {
        super.addOnPageChangeListener(listener);
        _Listeners.add(listener);
    }

    @Override
    public void removeOnPageChangeListener(OnPageChangeListener listener) {
        super.removeOnPageChangeListener(listener);
        _Listeners.remove(listener);
    }

    @Override
    public void setCurrentItem(final int item) {
        if (item != getCurrentItem()) {
            super.setCurrentItem(item);
        } else {
            post(new Runnable() {
                @Override
                public void run() {
                    dispatchOnPageSelected(item);
                }
            });
        }
    }

    private void dispatchOnPageSelected(int position) {
        for (int i = 0, size = _Listeners.size(); i < size; i++) {
            OnPageChangeListener listener = _Listeners.get(i);
            if (listener != null) {
                listener.onPageSelected(position);
            }
        }
    }
}

Ответ 11

@Override
public void addOnPageChangeListener(@NonNull OnPageChangeListener listener) {
    super.addOnPageChangeListener(listener);
    if (getAdapter() != null && getAdapter().getCount() > 0) {
        post(() -> listener.onPageSelected(getCurrentItem()));
    }
}