Ответ 1
Мы обошли это, повторно применяя элементы пейджера представления как стандартные представления, а не фрагменты и соответственно изменяя адаптер.
У меня есть интерфейс фрагмента с вкладками внизу, которые открывают разные фрагменты в основном представлении.
У меня есть один конкретный фрагмент, который является списком элементов. Если пользователь выбирает один из элементов в этом списке, открывается другой фрагмент, который содержит просмотрщик, который прокручивается по горизонтали между всеми элементами в списке в предыдущем фрагменте. Это отлично работает.
Viewpager использует FragmentPagerAdapter для отображения элементов.
Проблема возникает, когда пользователь выбирает элемент в списке, просматривает его, а затем нажимает кнопку на панели вкладок, чтобы вернуться к списку, затем выбирает другой элемент. Во второй раз, когда выбран элемент, вместо viewpager появляется пустой экран. Я не получаю ошибок в моем LogCat, когда это происходит.
Почему просмотрщик появляется только в первый раз?
FragmentPagerAdapter:
public class ViewPagerAdapter extends FragmentPagerAdapter {
Cursor mCursor;
public ViewPagerAdapter(FragmentManager fm, Cursor c) {
super(fm);
mCursor = c;
}
public void changeCursor(Cursor c) {
mCursor = c;
this.notifyDataSetChanged();
}
@Override
public int getCount() {
if (mCursor == null) return 0;
else return mCursor.getCount();
}
@Override
public Fragment getItem(int position) {
mCursor.moveToPosition(position);
return TeamCardFragment.newInstance(mCursor, position);
}
}
PagerFragment:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle bundle = getArguments();
mCursorPosition = bundle.getInt(TeamCardCommon.BUNDLE_KEY_CURSOR_POSITION);
View mView = inflater.inflate(R.layout.team_card_master, container, false);
mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager);
mAdapter = new ViewPagerAdapter(getFragmentManager(), cursor);
new setAdapterTask().execute();
return mView;
}
private class setAdapterTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
return null;
}
@Override
protected void onPostExecute(Void result) {
mViewPager.setAdapter(mAdapter);
mViewPager.setCurrentItem(mCursorPosition);
}
}
Мы обошли это, повторно применяя элементы пейджера представления как стандартные представления, а не фрагменты и соответственно изменяя адаптер.
У меня была такая же проблема. Изменение родительского класса моего PageAdapter от android.support.v4.app.FragmentPagerAdapter
до android.support.v4.app.FragmentStatePagerAdapter
во второй раз решит мою проблему с отображением ViewPager
!
Мне удалось решить эту проблему, заменив getFragmentManager()
на getChildFragmentManager()
в родительском фрагменте. Этот родительский фрагмент был экземпляром android.support.v4.app.FragmentPagerAdapter для того, чтобы содержать фрагменты с возможностью перемещения по страницам (скользящие), для чего требуется менеджер фрагментов в конструкторе. Этому конструктору я передал возвращаемое значение getChildFragmentManager()
.
ссылка на hackbod была ключевой (https://developer.android.com/about/versions/android-4.2.html#NestedFragments), которая была найдена в этом посте " Фрагменты внутри фрагментов"
Чтобы вложить фрагмент, просто вызовите
getChildFragmentManager()
для фрагмента, в который вы хотите добавить фрагмент. Это возвращает FragmentManager, который вы можете использовать, как обычно, из действия верхнего уровня для создания транзакций фрагмента.
для меня я должен был вызвать это на моем viewpager:
myViewPager.setSaveFromParentEnabled(false);
У меня возникла проблема, когда просмотрщик не был освежающим, и все, что я видел, было пустым белым экраном, на котором должны быть фрагменты. Я проходил в getChildFragmentManager, но это не помогло.
В моем конкретном случае, когда я использовал CoordinatorLayout с AppBarLayout и ViewPager, для меня это решило удалить андроид: fitsSystemWindows = "true" из моих свойств XML-объекта AppBarLayout.
Не спрашивай меня, почему. Я знаю, что это звучит немного смешно и, как будто это не должно иметь никакой корреляции, но именно эта единственная строка вызывала проблемы, поскольку я уже использовал getChildFragmentManager() в своем адаптере. Я потратил целый день на отладку своего кода, чтобы найти это, поэтому надеюсь, что он кого-то еще кого-нибудь спасет.
У меня была та же проблема, для которой я изменил адаптер с FragmentPagerAdapter
на FragmentStatePagerAdapter
и getFragmentManager()
в родительском фрагменте на getChildFragmentManager()
Причиной этого является то, что FragmentStatePagerAdapter
полезен для хранения большого количества страниц, и объем памяти, связанной с каждой посещаемой страницей, меньше, поскольку он сохраняет только сохраненное состояние фрагмента, пока страница не видна. Это уменьшает накладные расходы при переключении между фрагментами.
Это поможет вам.
viewPager.setOffscreenPageLimit(position);
Вы также можете инициализировать адаптер для случаев, когда эта ошибка возникает, когда ваше приложение сведено к минимуму и затем вызвано.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Bundle bundle = getArguments();
mCursorPosition = bundle.getInt(TeamCardCommon.BUNDLE_KEY_CURSOR_POSITION);
View mView = inflater.inflate(R.layout.team_card_master, container, false);
mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager);
initViewPagerAdapter();
return mView;
}
private void initViewPagerAdapter(){
mAdapter = new ViewPagerAdapter(getFragmentManager(), cursor);
new setAdapterTask().execute();
}
@Override
public void onResume(){
super.onResume();
initViewPagerAdapter();
}
У меня было то же самое, во второй раз, когда я вызываю Pager Adapter, дочерний вид возвращает исключение NullPointerException. И изменение адаптера в FragmentStatePagerAdapter также решит мою проблему.
Я получал ту же проблему на Xamarin Android с пустым экраном во второй раз. Установка следующего исправила это для меня.
viewPager.SaveFromParentEnabled = false;
Попробуйте установить setOffscreenPageLimit (int limit)
на родительский ViewPager.
mViewPager.setOffscreenPageLimit(totalPages-1);
Это сработало для меня как шарм.
В моем случае у меня был фрагмент внутри TabLayout
с ViewPager.
И еще один ViewPager
внутри этого фрагмента. В первый раз все работает нормально, но когда я перехожу на вкладку и возвращаюсь назад, часть моего фрагмента становится пустой.
Измените FragmentPagerAdapter
на FragmentStatePagerAdapter
Используйте getChildFragmentManager()
вместо getFragmentManager()
getChildFragmentManager()
- потому что согласно документации, он вернет частный FragmentManager для размещения и управления фрагментами внутри этого фрагмента. Между тем getFragmentManager()
вернет FragmentManager для взаимодействия с фрагментами, связанными с этим действием.