web-dev-qa-db-fra.com

Fragment dans ViewPager utilisant FragmentPagerAdapter est vide la deuxième fois qu'il est visualisé

J'ai une interface de fragment avec des onglets au bas qui ouvrent différents fragments dans la vue principale.

J'ai un fragment particulier qui est une liste d'éléments. Si l'utilisateur sélectionne l'un des éléments de cette liste, un autre fragment s'ouvre, qui contient un viewpager qui défile horizontalement entre tous les éléments de la liste du fragment précédent. Cela fonctionne très bien.

Le viewpager utilise un FragmentPagerAdapter pour afficher les éléments.

Le problème survient lorsque l'utilisateur sélectionne un élément de la liste, l'affiche, puis appuie sur le bouton de la barre d'onglets pour revenir à la liste, puis en sélectionne un autre. La deuxième fois qu'un élément est sélectionné, un écran vide apparaît à la place du viewpager. Je ne reçois aucune erreur dans mon LogCat lorsque cela se produit.

Pourquoi le viewpager n'apparaît-il que la première fois?

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);
    }
}
90
howettl

Nous avons contourné ce problème en ré-implémentant les éléments du pager view en tant que vues standard plutôt que fragments et en modifiant l'adaptateur en conséquence.

2
howettl

J'ai eu le même problème. Changer la classe parente de mon PageAdapter de Android.support.v4.app.FragmentPagerAdapter à Android.support.v4.app.FragmentStatePagerAdapter résout mon problème d'affichage ViewPager lors de la deuxième lecture!

210
Yann

J'ai réussi à résoudre ceci en remplaçant getFragmentManager() par getChildFragmentManager() dans le fragment parent. Ce fragment parent instanciait un Android.support.v4.app.FragmentPagerAdapter afin de contenir des fragments paginables (glissables), ce qui nécessite un gestionnaire de fragments dans le constructeur. À ce constructeur, j'ai passé la valeur de retour de getChildFragmentManager().

le lien de hackbod était la clé ( https://developer.Android.com/about/versions/Android-4.2.html#NestedFragments ), qui a été trouvé dans cet article Fragments de fragments

Pour imbriquer un fragment, appelez simplement getChildFragmentManager() sur le fichier Fragment dans lequel vous voulez ajouter un fragment. Ceci retourne un FragmentManager que vous pouvez utiliser comme vous le faites normalement à partir du fichier activité de niveau supérieur pour créer des transactions de fragment.

78
Daniel F

pour moi, j'ai dû appeler cela sur mon viewpager:

myViewPager.setSaveFromParentEnabled(false);

J'ai eu le problème où le viewpager n'était pas rafraîchissant et tout ce que j'ai vu était un écran blanc et blanc où les fragments devraient être. Je passais dans getChildFragmentManager mais cela n’a pas aidé. 

15
j2emanue

Dans mon cas très particulier, où j'utilisais un CoordinatorLayout avec un AppBarLayout et le ViewPager, ce qui me l'a résolu était de supprimer l'Android: fitsSystemWindows = "true" de mes propriétés xml AppBarLayout

Ne me demande pas pourquoi. Je sais que cela semble un peu ridicule et qu’il ne devrait pas y avoir de corrélation, mais c’est cette ligne unique qui posait problème, j’utilisais déjà getChildFragmentManager () dans mon adaptateur. J'ai passé toute une journée à déboguer mon code juste pour le trouver. J'espère donc que cela fera gagner du temps à quelqu'un d'autre.

8
emirua

J'ai eu le même problème pour lequel j'ai changé d'adaptateur de FragmentPagerAdapter à FragmentStatePagerAdapter et getFragmentManager() dans le fragment parent à getChildFragmentManager() 

La raison derrière cela est FragmentStatePagerAdapter est utile pour stocker un grand nombre de pages et la mémoire associée à chaque page visitée l'est moins car elle ne conserve que l'état de sauvegarde du fragment tant que la page n'est pas visible. Cela réduit les frais généraux lors du basculement entre les fragments. 

7
Yashaswi N P

Cela vous aiderait.

    viewPager.setOffscreenPageLimit(position);
2
Pardeep Singh

Essayez de mettre setOffscreenPageLimit (int limit) sur parent ViewPager.

mViewPager.setOffscreenPageLimit(totalPages-1);

Cela a fonctionné pour moi comme un charme.

Dans mon cas, j'avais un fragment dans TabLayout avec ViewPager.

Et une autre ViewPager à l'intérieur de ce fragment. La première fois, tout fonctionne bien, mais lorsque je change d’onglet et que je reviens, une partie de mon fragment est devenue vierge.

0
Rumit Patel

J'ai eu la même chose, la deuxième fois que j'ai appelé l'adaptateur de pageur, la vue enfant a renvoyé une exception NullPointerException ..__ et le changement de l'adaptateur dans FragmentStatePagerAdapter a également résolu mon problème.

0
Arka-57

Remplacez FragmentPagerAdapter par FragmentStatePagerAdapter Utilisez getChildFragmentManager() au lieu de getFragmentManager()

getChildFragmentManager() - parce que, selon la documentation, il renverra un gestionnaire de fragments privé pour placer et gérer les fragments à l'intérieur de ce fragment En attendant, getFragmentManager() renverra FragmentManager pour avoir interagi avec les fragments associés à cette activité.

0
Mostafa Anter

J'avais le même problème sur Xamarin Android avec un écran vide la deuxième fois. Le réglage suivant a résolu le problème.

viewPager.SaveFromParentEnabled = false;
0
Gerard

Vous pouvez également initialiser l'adaptateur dans les cas où vous rencontrez cette erreur lorsque votre application est réduite et appelée ultérieurement.

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