Фрагмент в ViewPager с использованием FragmentPagerAdapter пуст во второй раз, когда он просматривается - PullRequest
95 голосов
/ 13 октября 2011

У меня есть интерфейс фрагментов с вкладками внизу, которые открывают различные фрагменты в главном окне.

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

ViewPager использует FragmentPagerAdapter для отображения элементов.

Проблема возникает, когда пользователь выбирает элемент в списке, просматривает его, затем нажимает кнопку на панели вкладок, чтобы вернуться к списку, а затем выбирает другой элемент. При втором выборе элемента вместо окна просмотра появляется пустой экран. Когда это происходит, я не получаю ошибок в 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);
    }
}

Ответы [ 12 ]

215 голосов
/ 12 декабря 2011

У меня была такая же проблема.Изменение родительского класса моего PageAdapter с android.support.v4.app.FragmentPagerAdapter на android.support.v4.app.FragmentStatePagerAdapter решает мою ViewPager проблему с отображением во «второй раз»!

81 голосов
/ 27 марта 2014

Мне удалось решить эту проблему, заменив getFragmentManager() на getChildFragmentManager() в родительском фрагменте. Этот родительский фрагмент был экземпляром android.support.v4.app.FragmentPagerAdapter для того, чтобы содержать фрагменты, которые можно перемещать (скользящие), для чего требуется менеджер фрагментов в конструкторе. Этому конструктору я передал возвращаемое значение getChildFragmentManager().

Ссылка на hackbod была ключевой (https://developer.android.com/about/versions/android-4.2.html#NestedFragments),, которая была найдена в этом посте Фрагменты внутри фрагментов

Чтобы вложить фрагмент, просто наберите getChildFragmentManager() на Фрагмент, в который вы хотите добавить фрагмент. Это возвращает FragmentManager, который вы можете использовать, как обычно, из деятельность верхнего уровня для создания фрагментированных транзакций.

15 голосов
/ 12 июля 2017

для меня я должен был вызвать это на моем ViewPager:

myViewPager.setSaveFromParentEnabled(false);

У меня была проблема, когда ViewPager не обновлялся, и все, что я видел, было пустым белым экраном, где должны быть фрагменты.Я передавал в getChildFragmentManager, но это не помогло.

10 голосов
/ 22 июля 2016

В моем конкретном случае, когда я использовал CoordinatorLayout с AppBarLayout и ViewPager, для меня это решило удаление android: fitsSystemWindows = "true" из моих свойств xml AppBarLayout .

Не спрашивайте меня, почему. Я знаю, что это звучит немного нелепо и, как будто не должно быть никакой корреляции, но именно эта единственная строка вызывала проблемы, так как я уже использовал getChildFragmentManager () в своем адаптере. Я потратил целый день на отладку своего кода, просто чтобы найти его, поэтому я надеюсь, что это сэкономит кому-то еще время.

8 голосов
/ 16 августа 2017

У меня была та же проблема, для которой я изменил адаптер с FragmentPagerAdapter на FragmentStatePagerAdapter и getFragmentManager() в родительском фрагменте на getChildFragmentManager()

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

2 голосов
/ 21 августа 2018

Это поможет вам.

    viewPager.setOffscreenPageLimit(position);
1 голос
/ 04 октября 2018

Попробуйте поставить setOffscreenPageLimit (int limit) на родительский ViewPager.

mViewPager.setOffscreenPageLimit(totalPages-1);

Это сработало для меня как шарм.

В моем случаеУ меня был фрагмент внутри TabLayout с ViewPager.

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

1 голос
/ 29 ноября 2011

Мы обошли это путем повторной реализации элементов пейджинга представлений в виде стандартных представлений, а не фрагментов и соответствующей замены адаптера.

0 голосов
/ 23 октября 2018

Изменить FragmentPagerAdapter на FragmentStatePagerAdapter Использовать getChildFragmentManager() вместо getFragmentManager()

getChildFragmentManager() - потому что согласно документации, он вернет частный FragmentManager для размещения и управления фрагментами внутри этого фрагмента,Между тем getFragmentManager() вернет FragmentManager для взаимодействия с фрагментами, связанными с этим действием

0 голосов
/ 03 сентября 2017

Я получал эту же проблему на Xamarin Android с пустым экраном во второй раз.

...