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