Здесь у нас возникла очень странная проблема с ViewPager. Мы встраиваем списки на каждую страницу ViewPager и запускаем notifyDataSetChanged как в адаптере списка, так и в адаптере пейджера просмотра при обновлении данных списка.
Что мы наблюдаем, так это то, что иногда страница не обновляет свое дерево представления, то есть остается пустой, а иногда даже исчезает при перелистывании страницы. При перелистывании назад и вперед несколько раз содержимое внезапно появляется снова. Кажется, что Android здесь отсутствует обновление представления. Я также заметил, что при отладке с помощью средства просмотра иерархии выбор представления всегда приводит к его повторному появлению, по-видимому, потому, что средство просмотра иерархии заставляет выбранный вид перерисовывать себя.
Я не мог сделать это программно; аннулирование представления списка или даже всей страницы просмотра не имело никакого эффекта.
Это с библиотекой совместимости v4_r7. Я также пытался использовать последнюю версию, поскольку она утверждает, что исправляет многие проблемы, связанные с просмотром пейджера, но это усугубило ситуацию (например, были нарушены жесты, так что это не позволяло мне иногда пролистывать все страницы)
Кто-нибудь еще сталкивается с этими проблемами, или вы знаете, что может быть причиной этого?
источник
Если
ViewPager
установлен внутри фрагмента с помощьюFragmentPagerAdapter
, используйтеgetChildFragmentManager()
вместоgetSupportFragmentManager()
параметра для инициализации вашегоFragmentPagerAdapter
.mAdapter = new MyFragmentPagerAdapter(getChildFragmentManager());
Вместо того
mAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager());
источник
getItem()
объект,FragmentPagerAdapter
который был вложен в воссозданный фрагмент.У меня была такая же проблема, но я фактически уничтожил представление в destroyItem (я думал). Однако проблема заключалась в том, что я уничтожил его, используя
viewPager.removeViewAt(index);
insted ofviewPager.removeView((View) object);
Неправильно:
@Override public void destroyItem(ViewGroup viewPager, int position, Object object) { viewPager.removeViewAt(position); }
Правильно:
@Override public void destroyItem(ViewGroup viewPager, int position, Object object) { viewPager.removeView((View) object); }
источник
ViewPager пытается делать умные вещи вокруг повторного использования элементов, но он требует, чтобы вы возвращали новые позиции элементов, когда что-то изменилось. Попробуйте добавить это в свой PagerAdapter:
public int getItemPosition (Object object) { return POSITION_NONE; }
По сути, он сообщает ViewPager, что все изменилось (и заставляет его заново создать экземпляр). Это единственное, о чем я могу прийти в голову.
источник
return POSITION_NONE;
,forces it to re-instantiate everything
но в моем случае я не хочу повторно создавать все , поэтому можно ли удалить,view
не очищая существующие вещи? Пожалуйста, дайте мне знатьПробовал слишком много решений, но неожиданно
viewPager.post()
сработалоmAdapter = new NewsVPAdapter(getContext(), articles); viewPager.post(new Runnable() { @Override public void run() { viewPager.setAdapter(mAdapter); } });
источник
В библиотеке поддержки Android есть демонстрация Activity, которая включает ViewPager со ListView на каждой странице. Вам, вероятно, стоит взглянуть и увидеть, что он делает.
В Eclipse (с Android Dev Tools r20):
New > Android Sample Project
Support4Demos
Android Tools > Add Support Library
Fragment
а затемPager
Код для этого находится в
src/com.example.android.supportv4.app/FragmentPagerSupport.java
. Удачи!источник
Я столкнулся с этим и имел очень похожие проблемы. Я даже спрашивал о переполнении стека.
Для меня в родительском элементе родительского элемента моего представления кто-то подклассифицировал
LinearLayout
и переопределилrequestLayout()
без вызоваsuper.requestLayout()
. Это предотвратилоonMeasure
иonLayout
не вызвало мой ViewPager (хотя иерархия вызывает их вручную). Без измерения они будут отображаться в ViewPager как пустые.Так что проверьте свои содержащие представления. Убедитесь, что они являются подклассом View и не переопределяют слепо requestLayout или что-либо подобное.
источник
Имел ту же проблему, что связано с
ListView
(потому что мое пустое представление отображается нормально, если список пуст). Я просто позвонилrequestLayout()
проблемномуListView
. Теперь отлично рисует!источник
Я столкнулся с этой же проблемой при использовании ViewPager и FragmentStatePagerAdapter. Я попытался использовать обработчик с 3-секундной задержкой для вызова invalidate () и requestLayout (), но это не сработало. Что действительно помогло, так это сбросить цвет фона viewPager следующим образом:
MyFragment.java
private Handler mHandler; private Runnable mBugUpdater; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = new ViewPager(getActivity()); //...Create your adapter and set it here... mHandler = new Handler(); mBugUpdater = new Runnable(){ @Override public void run() { mVp.setBackgroundColor(mItem.getBackgroundColor()); mHandler = null; mBugUpdater = null; } }; mHandler.postDelayed(mBugUpdater,50); return rootView; } @Override public void onPause() { if(mHandler != null){ //Remove the callback if it hasn't triggered yet mHandler.removeCallbacks(mBugUpdater); mHandler = null; mBugUpdater = null; } super.onPause(); }
источник
У меня была проблема с теми же симптомами, но по другой причине, которая оказалась с моей стороны глупой ошибкой. Думал, что добавлю его сюда, если это кому-то поможет.
У меня был ViewPager, использующий FragmentStatePagerAdapter, который раньше имел два фрагмента, но позже я добавил третий. Однако я забыл, что ограничение по умолчанию для страниц вне экрана равно 1, поэтому, когда я переключусь на новый третий фрагмент, первый будет уничтожен, а затем воссоздан после переключения обратно. Проблема заключалась в том, что я отвечал за уведомление этих фрагментов для инициализации их состояния пользовательского интерфейса. Это сработало, когда жизненные циклы активности и фрагмента были одинаковыми, но чтобы исправить это, мне пришлось изменить фрагменты, чтобы инициализировать их собственный пользовательский интерфейс во время их жизненного цикла запуска. В конце концов, я также изменил setOffscreenPageLimit на 2, чтобы все три фрагмента всегда оставались активными (безопасно в этом случае, поскольку они не очень интенсивно потребляли память).
источник
У меня была аналогичная проблема. Я кэширую просмотры, потому что мне нужно всего 3 просмотра
ViewPager
. Когда я двигаюсь вперед, все в порядке, но когда я начинаю скользить назад, возникает ошибка, в которой говорится, что «у моего представления уже есть родительский элемент». Решение - удалить ненужные элементы вручную.@Override public Object instantiateItem(ViewGroup container, int position) { int localPos = position % SIZE; TouchImageView view; if (touchImageViews[localPos] != null) { view = touchImageViews[localPos]; } else { view = new TouchImageView(container.getContext()); view.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); touchImageViews[localPos] = view; } view.setImageDrawable(mDataModel.getPhoto(position)); Log.i(IRViewPagerAdpt.class.toString(), "Add view " + view.toString() + " at pos: " + position + " " + localPos); if (view.getParent() == null) { ((ViewPager) container).addView(view); } return view; } @Override public void destroyItem(ViewGroup container, int position, Object view) { // ((ViewPager) container).removeView((View) view); Log.i(IRViewPagerAdpt.class.toString(), "remove view " + view.toString() + " at pos: " + position); } .................. private static final int SIZE = 3; private TouchImageView[] touchImageViews = new TouchImageView[SIZE];
источник
Для меня проблема заключалась в возвращении к активности после того, как процесс приложения был убит. Я использую настраиваемый адаптер пейджера представления, модифицированный из источников Android. Пейджер представления встроен непосредственно в действие.
Вызов
viewPager.setCurrentItem(position, true);
(с анимацией) после установки данных и notifyDataSetChanged () похоже, работает, но если для параметра установлено значение false, это не так, и фрагмент пустой. Это крайний случай, который может кому-то помочь.
источник