102 votes

Le fragment dans le ViewPager utilisant FragmentPagerAdapter est vide la deuxième fois qu'il est visualisé.

J'ai une interface de fragment avec des onglets en 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 et contient un viewpager qui fait défiler horizontalement 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, le visualise, puis appuie sur le bouton de la barre d'onglets pour revenir à la liste, puis sélectionne un autre élément. 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);
    }
}

223voto

B00merang Points 971

J'ai eu le même problème. En changeant la classe mère de mon PageAdapter de android.support.v4.app.FragmentPagerAdapter a android.support.v4.app.FragmentStatePagerAdapter résoudre mon ViewPager problème d'affichage lors de la "deuxième fois" !

2 votes

Sans blague ? Je n'ai plus ce code sinon je le testerais. Peut-être que cette réponse aidera quelqu'un d'autre.

10 votes

Quel homme ! J'étais à la recherche de cette solution depuis des jours ! Merci beaucoup, ça marche du tonnerre. Mais le développeur en moi se demande quel est l'impact de ce changement ? Je veux dire pourquoi cela ne fonctionnait pas avant et pourquoi dans StatePagerAdapter

1 votes

Vous devez également @Override public int getItemPosition (Object object) { return POSITION_NONE ; }

89voto

Daniel F. Points 836

J'ai réussi à résoudre ce problème en remplaçant getFragmentManager() con getChildFragmentManager() dans le fragment parent. Ce fragment parent instanciait un Android.support.v4.app.FragmentPagerAdapter afin de contenir des fragments pouvant être mis en page (glissés), 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 essentiel ( https://developer.Android.com/about/versions/Android-4.2.html#NestedFragments ), qui a été trouvé dans ce post Fragments dans les fragments

Pour imbriquer un fragment, il suffit d'appeler getChildFragmentManager() sur la Fragment dans lequel vous souhaitez ajouter un fragment. Cela renvoie un FragmentManager que vous pouvez utiliser comme vous le faites normalement à partir de l'activité de premier niveau pour ajouter des fragments. pour créer des transactions de fragments.

0 votes

Merci... j'avais un problème similaire en essayant de ré-instancier une vue d'onglets coulissants après onresume() qui contenait un fragmentpageradapter... le tutoriel que j'ai utilisé datait de 2016 et je devais toujours le changer en fragmentstatepageradapter pour que cela fonctionne. j'aurais aimé savoir pourquoi.

0 votes

Cette réponse m'a fait gagner beaucoup de temps. Parce qu'il suffit d'utiliser FragmentStatePagerAdapter ne résout pas la question posée ici. avec FragmentStatePagerAdapter dans le fragment parent YourAdapter adapter = new YourAdapter (getChildFragmentManager()); doit être ajouté

18voto

j2emanue Points 3456

Pour ma part, j'ai dû l'appeler sur mon viewpager :

myViewPager.setSaveFromParentEnabled(false);

J'ai eu un problème avec le viewpager qui ne se rafraichissait pas et tout ce que je voyais c'était un écran blanc à la place des fragments. Je passais dans getChildFragmentManager mais cela n'a pas aidé.

11voto

emirua Points 400

Dans mon cas très particulier, où j'utilisais un CoordinatorLayout avec un AppBarLayout et le ViewPager, j'ai trouvé la solution suivante suppression de Android:fitsSystemWindows="true" de mes propriétés AppBarLayout xml .

Ne me demandez pas pourquoi. Je sais que cela semble un peu ridicule et que cela ne devrait pas avoir de corrélation, mais cette seule ligne était la seule chose qui causait des problèmes car j'utilisais déjà getChildFragmentManager() dans mon adaptateur. J'ai passé une journée entière à déboguer mon code juste pour trouver cela, alors j'espère que cela fera gagner du temps à quelqu'un d'autre.

10voto

Yashaswi N P Points 480

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

La raison en est la suivante FragmentStatePagerAdapter est utile pour stocker un grand nombre de pages et la mémoire associée à chaque page visitée est moindre car il ne conserve que l'état sauvegardé du fragment lorsque la page n'est pas visible. Cela réduit la charge de travail lors du passage d'un fragment à l'autre.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X