Récupérer un fragment d'un ViewPager

248

J'utilise un ViewPagerensemble avec un FragmentStatePagerAdapterpour héberger trois fragments différents:

  • [Fragment1]
  • [Fragment2]
  • [Fragment3]

Quand je veux sortir Fragment1de ViewPagerla FragmentActivity.

Quel est le problème et comment le résoudre?

Qun Qin
la source

Réponses:

504

La réponse principale repose sur un nom généré par le framework. Si cela change, cela ne fonctionnera plus.

Qu'en est-il de cette solution, prioritaire instantiateItem()et destroyItem()de votre Fragment(State)PagerAdapter:

public class MyPagerAdapter extends FragmentStatePagerAdapter {
    SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();

    public MyPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public int getCount() {
        return ...;
    }

    @Override
    public Fragment getItem(int position) {
        return MyFragment.newInstance(...); 
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Fragment fragment = (Fragment) super.instantiateItem(container, position);
        registeredFragments.put(position, fragment);
        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        registeredFragments.remove(position);
        super.destroyItem(container, position, object);
    }

    public Fragment getRegisteredFragment(int position) {
        return registeredFragments.get(position);
    }
}

Cela semble fonctionner pour moi lorsqu'il s'agit de fragments disponibles. Les fragments qui n'ont pas encore été instanciés, renverront null lors de l'appel getRegisteredFragment. Mais j'ai utilisé cela principalement pour extraire le courant Fragmentdu ViewPager: adapater.getRegisteredFragment(viewPager.getCurrentItem())et cela ne reviendra pas null.

Je ne connais aucun autre inconvénient de cette solution. S'il y en a, j'aimerais savoir.

Rues de Boston
la source
41
C'est aussi la meilleure solution à laquelle je peux penser. Seule suggestion serait d'envelopper peut - être le Fragmentdans WeakReferencede vous garantir ne pas empêcher un fragment d'être détruit ordures collectées? Semble juste la bonne chose à faire ...
Alex Lockwood
7
Que se passe-t-il quand MyPagerAdapterest détruit en raison du cycle de vie (c'est-à-dire en rotation), ne sera pas registerdFragmentsperdu? Est-ce que le Activity/ Fragmentutilisant MyPagerAdapterdoivent enregistrer dans onSaveInstanceStateet alors besoin de le mettre à jour avec la nouvelle FragmentManagerref?
Steven Byle
10
Si je ne me trompe pas (et vous devriez vérifier cela), la méthode getItem n'est pas appelée - comme vous le savez - mais la méthode instantiateItem est appelée pour chaque fragment qui est restauré par le framework après une rotation.
Streets Of Boston
6
Oui, j'ai vérifié qu'il getItemne sera pas appelé à nouveau lors de la rotation (pour les frags déjà créés), car le FragmentManagerrestaure les états du Fragmentscontenu dans le pager. Si instantiateItemest appelé lorsque chacun Fragmentest restauré, cette solution est en fait plus sûre et plus pérenne que la mienne ou la réponse acceptée. J'envisagerai de l'essayer moi-même.
Steven Byle
6
@ Dori, je ne le casse pas. Ma solution n'utilise pas le résultat de l'appel «getItem ()». Au lieu de cela, il utilise le résultat stocké à partir de l'appel «instantiateItem ()». Et le cycle de vie du fragment n'est pas interrompu, car le fragment stocké sera supprimé du tableau clairsemé lors de l'appel à destroyItem ().
Streets Of Boston
85

Pour récupérer des fragments d'un ViewPager, il y a beaucoup de réponses ici et sur d'autres threads / blogs SO connexes. Tous ceux que j'ai vus sont brisés et ils semblent généralement appartenir à l'un des deux types énumérés ci-dessous. Il existe d'autres solutions valides si vous souhaitez uniquement récupérer le fragment actuel, comme celui-ci autre réponse sur ce fil.

Si vous utilisez, FragmentPagerAdaptervoir ci-dessous. Si cela FragmentStatePagerAdaptervaut la peine de regarder cela . Saisir des index qui ne sont pas ceux en cours dans un FragmentStateAdapter n'est pas aussi utile que par leur nature, ils seront complètement détruits hors de vue / hors des limites offScreenLimit.

LES CHEMINS INUTILES

Mauvais: conservez votre propre liste interne de fragments, ajoutée au moment de l' FragmentPagerAdapter.getItem()appel

  • Utilisant généralement un SparseArrayouMap
  • Aucun des nombreux exemples que j'ai vus ne rend compte des événements du cycle de vie, cette solution est donc fragile. Comme cela getItemn'est appelé que la première fois qu'une page est défilée vers (ou obtenue si votre ViewPager.setOffscreenPageLimit(x)> 0) dans le ViewPager, si l'hébergement Activity/ Fragmentest tué ou redémarré, alors l'interne SpaseArraysera effacé lorsque le FragmentPagerActivity personnalisé est recréé, mais en coulisses le ViewPagers fragments internes seront recréés et getItemseront pas appelés pour l' un des indices, donc la possibilité d'obtenir un fragment de l' indice seront perdus à jamais. Vous pouvez en tenir compte en enregistrant et en restaurant ces références de fragments via FragmentManager.getFragment()et putFragmentmais cela commence à devenir IMHO désordonné.

Mauvais: créez votre propre identifiant de balise correspondant à ce qui est utilisé sous le capotFragmentPagerAdapter et utilisez-le pour récupérer les fragments de page de laFragmentManager

  • C'est mieux dans la mesure où il résout le problème de perte de fragments-références dans la première solution de tableau interne, mais comme indiqué à juste titre dans les réponses ci-dessus et ailleurs sur le net - il se sent hacky comme sa méthode privée interne à ViewPagercela pourrait changer à tout moment ou pour toute version du système d'exploitation.

La méthode recréée pour cette solution est

private static String makeFragmentName(int viewId, long id) {
    return "android:switcher:" + viewId + ":" + id;
}

UN CHEMIN HEUREUX: ViewPager.instantiateItem()

Une approche similaire à celle getItem()ci-dessus mais sans rupture de cycle de vie consiste à s'y connecter au instantiateItem()lieu de getItem()car la première sera appelée à chaque fois que l'index est créé / accédé. Voir cette réponse

UN CHEMIN HEUREUX: Construisez le vôtre FragmentViewPager

Construisez votre propre FragmentViewPagerclasse à partir de la source de la dernière bibliothèque de support et modifiez la méthode utilisée en interne pour générer les balises de fragment. Vous pouvez le remplacer par ce qui suit. Cela a l'avantage que vous savez que la création de balises ne changera jamais et que vous ne comptez pas sur une API / méthode privée, ce qui est toujours dangereux.

/**
 * @param containerViewId the ViewPager this adapter is being supplied to
 * @param id pass in getItemId(position) as this is whats used internally in this class
 * @return the tag used for this pages fragment
 */
public static String makeFragmentName(int containerViewId, long id) {
    return "android:switcher:" + containerViewId + ":" + id;
}

Ensuite, comme le dit le doc, lorsque vous voulez récupérer un fragment utilisé pour un index, appelez simplement quelque chose comme cette méthode (que vous pouvez mettre dans la coutume FragmentPagerAdapterou une sous-classe) sachant que le résultat peut être nul si getItem n'a pas encore été appelé pour cette page c'est-à-dire qu'elle n'a pas encore été créée.

/**
 * @return may return null if the fragment has not been instantiated yet for that position - this depends on if the fragment has been viewed
 * yet OR is a sibling covered by {@link android.support.v4.view.ViewPager#setOffscreenPageLimit(int)}. Can use this to call methods on
 * the current positions fragment.
 */
public @Nullable Fragment getFragmentForPosition(int position)
{
    String tag = makeFragmentName(mViewPager.getId(), getItemId(position));
    Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag);
    return fragment;
}

Il s'agit d'une solution simple qui résout les problèmes des deux autres solutions trouvées partout sur le Web

Dori
la source
6
Cela fonctionnera, mais cela nécessite de copier la classe ViewPager dans votre propre code source. S'appuyer sur les 'instantiateItem ()' et 'destroyItem ()' de l'adaptateur de pageur d'un ViewPager fonctionnera et honorera les cycles de vie des fragments (ces 2 méthodes sont également appelées lorsque des fragments sont créés à partir d'un état d'instance enregistré). Vous avez raison, s'appuyer sur «getItem ()» n'est pas une bonne idée et utiliser des API privées ne l'est pas non plus.
Streets Of Boston
+1 J'accepte que c'est aussi une solution et j'ai édité ci-dessus. La seule différence est que ce qui précède fonctionne dans un cas d'utilisation de plus que instantiateItem()lorsque vous souhaitez accéder à un fragment qui n'a pas encore été visité après qu'un événement de cycle de vie a eu lieu et a été visité avant l'événement de cycle de vie. Une petite différence que je connais mais c'est celle qui a conduit à un bug subtil dans mon programme, donc je me suis penché sur cela.
Dori
Si setOffscreenPageLimit = 1 (par défaut), FragmentStatePageAdapter commencera à échanger des fragments dans et hors de la mémoire lors de l'accès aux pages de visualisation. Par un appel à getItem (), une nouvelle instance de pages / fragments revisités sera alors créée. Lors d'une telle révision, existe-t-il un moyen de demander au système de reprendre les instances précédemment créées, plutôt que d'en créer une nouvelle?
carl
si en dehors de la limite de pages, il devra en créer une nouvelle - mais en passant dans l'état enregistré. Si vous souhaitez conserver les anciens, vous pouvez augmenter la limite de pages
Dori
@Dori il n'y a pas à l' getItemId(pos)intérieurFragmentStatePagerAdapter
Jemshit Iskenderov
70

Ajoutez les méthodes suivantes à votre FragmentPagerAdapter:

public Fragment getActiveFragment(ViewPager container, int position) {
String name = makeFragmentName(container.getId(), position);
return  mFragmentManager.findFragmentByTag(name);
}

private static String makeFragmentName(int viewId, int index) {
    return "android:switcher:" + viewId + ":" + index;
}

getActiveFragment (0) doit fonctionner.

Voici la solution implémentée dans ViewPager https://gist.github.com/jacek-marchwicki/d6320ba9a910c514424d . Si quelque chose échoue, vous verrez un bon journal des plantages.

kzotin
la source
Merci beaucoup:) . À travers, je l'ai mélangé d'une autre manière que j'utilise un gestionnaire pour publier le fragment. Ce n'est pas très approprié mais cela a finalement réglé le problème. Au fait, vous êtes sympa :)
Qun Qin
12
J'utilisais cette méthode, mais je pense qu'elle a cessé de fonctionner lorsque je suis passé à l'API 17 (?). Je recommanderais une autre méthode, et je préférerais que Google publie simplement une API pour récupérer un fragment d'un ViewPager, compte tenu de sa position.
gcl1
j'ai du mal à appeler le deuxième fragment, la méthode en crée un nouveau
Vasil Valchev
2
Étant donné qu'une certaine version de l'API, la méthode makeFragmentName a été remplacée par une chaîne statique statique makeFragmentName (int viewId, long id) {return "android: switcher:" + viewId + ":" + id; } donc la méthode getActiveFragment devrait maintenant ressembler à ceci (utiliser getItemId au lieu de position pour le deuxième argument) public Fragment getActiveFragment (conteneur ViewPager, position int) {String name = makeFragmentName (container.getId (), getItemId (position)); return mFragmentManager.findFragmentByTag (nom); }
Eugene Popovich
1
Cela fonctionne vraiment, mais c'est vraiment dangereux car il s'appuie sur l'implémentation interne du pager de vue et si Google va changer l'implémentation (et ils peuvent), de mauvaises choses vont se produire. J'espère vraiment que goole le rendra disponible pour obtenir le fragment live
shem
38

Une autre solution simple:

    public class MyPagerAdapter extends FragmentPagerAdapter {
        private Fragment mCurrentFragment;

        public Fragment getCurrentFragment() {
            return mCurrentFragment;
        }
//...    
        @Override
        public void setPrimaryItem(ViewGroup container, int position, Object object) {
            if (getCurrentFragment() != object) {
                mCurrentFragment = ((Fragment) object);
            }
            super.setPrimaryItem(container, position, object);
        }
    }
Mindphaser
la source
1
Cela semble parfait pour mes besoins de fragments actuels.
danny117
Si tout ce que vous avez à faire est d'obtenir le fragment actuellement sélectionné, c'est tout ce dont vous avez besoin - la méthode setPrimaryItem est définie sur attach et également sur chaque mise à jour de l'ensemble interne du fragment en tant qu'élément actuel.
Graeme
1
Cela semble être une bonne solution mais comme setPrimaryItem()on l'appelle après ViewPager.OnPageChangeListener#onPageSelected() je ne peux pas l'utiliser :-(
hardysim
21

Je sais que cela a quelques réponses, mais peut-être que cela aidera quelqu'un. Je l' ai utilisé une solution relativement simple quand je avais besoin pour obtenir un Fragmentde mes ViewPager. Dans votre Activityou en Fragmentmaintenant le ViewPager, vous pouvez utiliser ce code pour parcourir chaque Fragmentcontenu.

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
    Fragment viewPagerFragment = fragmentPagerAdapter.getItem(i);
    if(viewPagerFragment != null) {
        // Do something with your Fragment
        // Check viewPagerFragment.isResumed() if you intend on interacting with any views.
    }
}
  • Si vous connaissez la position de votre Fragmentdans le ViewPager, vous pouvez simplement appeler getItem(knownPosition).

  • Si vous ne connaissez pas la position de votre Fragmentdans le ViewPager, vous pouvez demander à vos enfants d' Fragmentsimplémenter une interface avec une méthode comme getUniqueId(), et de l'utiliser pour les différencier. Ou vous pouvez parcourir tout Fragmentset vérifier le type de classe, tel queif(viewPagerFragment instanceof FragmentClassYouWant)

!!! ÉDITER !!!

J'ai découvert que getItemseulement est appelé par un FragmentPagerAdapterlorsque chacun Fragmentdoit être créé la première fois , après cela, il semble que le Fragmentssont recyclés à l'aide du FragmentManager. De cette façon, de nombreuses implémentations de FragmentPagerAdaptercreate new Fragment s in getItem. En utilisant ma méthode ci-dessus, cela signifie que nous créerons de nouveaux Fragments à chaque getItemappel lorsque nous parcourons tous les éléments du FragmentPagerAdapter. Pour cette raison, j'ai trouvé une meilleure approche, en utilisant le FragmentManagerpour obtenir chacun à la Fragmentplace (en utilisant la réponse acceptée). Il s'agit d'une solution plus complète qui fonctionne bien pour moi.

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
    String name = makeFragmentName(mViewPager.getId(), i);
    Fragment viewPagerFragment = getChildFragmentManager().findFragmentByTag(name);
    // OR Fragment viewPagerFragment = getFragmentManager().findFragmentByTag(name);
    if(viewPagerFragment != null) {

        // Do something with your Fragment
        if (viewPagerFragment.isResumed()) {
            // Interact with any views/data that must be alive
        }
        else {
            // Flag something for update later, when this viewPagerFragment
            // returns to onResume
        }
    }
}

Et vous aurez besoin de cette méthode.

private static String makeFragmentName(int viewId, int position) {
    return "android:switcher:" + viewId + ":" + position;
}
Steven Byle
la source
1
Vous venez de trouverFragmentByTag (), mais où pourrions-nous définir le TAG avec un fragment ??
VinceStyling
@vince The ViewPagerlui-même définit ces balises. Cette solution est fragile car elle repose sur la connaissance de la convention de nommage "cachée" du ViewPager. La réponse de Streets of Boston est une solution beaucoup plus complète, que j'utilise maintenant dans mon projet (au lieu de cette approche).
Steven Byle
Cela fonctionne très bien! Mais j'ai supprimé la condition "if (viewPagerFragment.isResumed ())" car j'ai besoin de mettre à jour mes pages ListFragment hors écran. Ensuite, lorsque l'utilisateur revient à la page ListFragment, tout est mis à jour avec les nouvelles données.
JDJ
10

Pour mon cas, aucune des solutions ci-dessus n'a fonctionné.

Cependant, puisque j'utilise le gestionnaire de fragments d'enfant dans un fragment, les éléments suivants ont été utilisés:

Fragment f = getChildFragmentManager().getFragments().get(viewPager.getCurrentItem());

Cela ne fonctionnera que si vos fragments dans le gestionnaire correspondent à l'élément du viseur.

Veedka
la source
C'est la réponse parfaite pour obtenir de vieux fragments du pageur de vue lorsque l'activité ou le fragment est recréé.
Smeet
7

Afin d'obtenir le fragment visible actuel de ViewPager . J'utilise cette simple déclaration et cela fonctionne bien.

      public Fragment getFragmentFromViewpager()  
      {
         return ((Fragment) (mAdapter.instantiateItem(mViewPager, mViewPager.getCurrentItem())));
      }
Zar E Ahmer
la source
3

Je l'ai manipulé en faisant d'abord une liste de tous les fragments ( List<Fragment> fragments;) que j'allais utiliser, puis je les ai ajoutés au pager, ce qui facilite la gestion du fragment actuellement affiché.

Alors:

@Override
onCreate(){
    //initialise the list of fragments
    fragments = new Vector<Fragment>();

    //fill up the list with out fragments
    fragments.add(Fragment.instantiate(this, MainFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, MenuFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, StoresFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, AboutFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, ContactFragment.class.getName()));


    //Set up the pager
    pager = (ViewPager)findViewById(R.id.pager);
    pager.setAdapter(new MyFragmentPagerAdapter(getSupportFragmentManager(), fragments));
    pager.setOffscreenPageLimit(4);
}

alors cela peut être appelé:

public Fragment getFragment(ViewPager pager){   
    Fragment theFragment = fragments.get(pager.getCurrentItem());
    return theFragment;
}

alors je pourrais le jeter dans une instruction if qui ne fonctionnerait que si elle était sur le bon fragment

Fragment tempFragment = getFragment();
if(tempFragment == MyFragmentNo2.class){
    MyFragmentNo2 theFrag = (MyFragmentNo2) tempFragment;
    //then you can do whatever with the fragment
    theFrag.costomFunction();
}

mais c'est juste mon approche de hack et slash mais cela a fonctionné pour moi, je l'utilise pour apporter des modifications pertinentes à mon fragment actuellement affiché lorsque le bouton de retour est enfoncé.

Russell Cargill
la source
1
meilleure réponse pour moi
Sonu Kumar
3

Ceci est basé sur la réponse de Steven ci-dessus. Cela retournera une instance réelle du fragment qui est déjà attaché à l'activité parent.

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
    for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {

        Fragment viewPagerFragment = (Fragment) mViewPager.getAdapter().instantiateItem(mViewPager, i);
        if(viewPagerFragment != null && viewPagerFragment.isAdded()) {

            if (viewPagerFragment instanceof FragmentOne){
                FragmentOne oneFragment = (FragmentOne) viewPagerFragment;
                if (oneFragment != null){
                    oneFragment.update(); // your custom method
                }
            } else if (viewPagerFragment instanceof FragmentTwo){
                FragmentTwo twoFragment = (FragmentTwo) viewPagerFragment;

                if (twoFragment != null){
                    twoFragment.update(); // your custom method
                }
            }
        }
    }
Oranger
la source
2

Je ne pouvais pas trouver un moyen simple et propre de le faire. Cependant, le widget ViewPager n'est qu'un autre ViewGroup, qui héberge vos fragments. Le ViewPager a ces fragments en tant qu'enfants immédiats. Vous pouvez donc simplement les parcourir (en utilisant .getChildCount () et .getChildAt ()), et voir si l'instance de fragment que vous recherchez est actuellement chargée dans le ViewPager et obtenir une référence. Par exemple, vous pouvez utiliser un champ ID unique statique pour distinguer les fragments.

Notez que le ViewPager n'a peut-être pas chargé le fragment que vous recherchez car il s'agit d'un conteneur de virtualisation comme ListView.

Zsombor Erdődy-Nagy
la source
1
Merci pour votre réponse, je la récupère avec l'adpter.getItem (); Je suis un étudiant de première année en programmation Android. vous apprécie vraiment beaucoup. Maintenant, je peux récupérer le ListFragment et je veux y ajouter footerView, alors que je le fais dans mon activité, puis l'impression logcat: "java.lang.IllegalStateException: la vue de contenu n'est pas encore. Créée". Je sais pourquoi mais j'ai des difficultés à gérer avec ça.
Qun Qin
1
FragmentActivity a la méthode onAttachFragment (), dose ce travail pour le contenu du fragment ViewPager?
Vasil Valchev
2

FragmentPagerAdapter est la fabrique des fragments. Pour trouver un fragment basé sur sa position s'il est encore en mémoire, utilisez ceci:

public Fragment findFragmentByPosition(int position) {
    FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter();
    return getSupportFragmentManager().findFragmentByTag(
            "android:switcher:" + getViewPager().getId() + ":"
                    + fragmentPagerAdapter.getItemId(position));
}

Exemple de code pour l'API de support v4.

Daniel De León
la source
Il retourne null dans onresume (). Une idée pourquoi et houe pour le réparer?
seema
2

Vous n'avez pas besoin d'appeler getItem()ou d'une autre méthode à un stade ultérieur pour obtenir la référence d'un Fragmenthébergé à l'intérieur ViewPager. Si vous souhaitez mettre à jour certaines données à l'intérieur, Fragmentutilisez cette approche: Mettre à jour ViewPager dynamiquement?

La clé est de définir de nouvelles données à l'intérieur Adaperet d'appeler notifyDataSetChanged()qui à leur tour appellera getItemPosition(), vous transmettant une référence Fragmentet vous donnant la possibilité de la mettre à jour. Toutes les autres façons vous obligent à garder une référence à vous-même ou à un autre piratage qui n'est pas une bonne solution.

@Override
public int getItemPosition(Object object) {
    if (object instanceof UpdateableFragment) {
        ((UpdateableFragment) object).update(xyzData);
    }
    //don't return POSITION_NONE, avoid fragment recreation. 
    return super.getItemPosition(object);
}
M-WaJeEh
la source
Je ne comprends pas ici, vous avez besoin d'une référence d'un Fragment pour utiliser getItemPosition (), donc vous pourriez aussi bien ne pas utiliser getItemPosition, hein?
getItemPosition()est une méthode dans votre adaptateur. Vous ne l'appellerez pas directement. Vous avez une référence de votre adaptateur donc vous appelez adapter.notifyDataSetChanged()qui à son tour appellera getItemPosition()de votre adaptateur en passant la référence de votre Fragments. Vous pouvez voir une implémentation complète en action ici stackoverflow.com/questions/19891828/…
M-WaJeEh
J'ai relu cela et je ne comprends toujours pas. Vous auriez toujours besoin d'une référence directe à ces fragments afin de faire des appels contre eux, non? Vous mentionnez cela comme un hack mais je ne vois pas d'alternative; adapter.getItem (i) ne va évidemment pas fonctionner.
2
Ok, j'ai mis à jour ma réponse pour clarifier davantage. Bien sûr, une référence est nécessaire pour mettre à jour un Fragmentmais comment obtenir une référence est discutable. D'autres solutions obtiennent des références en FragmentManagerutilisant une chaîne similaire à "android:switcher:"+idou en revenant POSITION_NONEde getItemosition()provoquer la recréation de tous les fragments.
M-WaJeEh
Merci, cela a beaucoup plus de sens et correspond à mon expérience (donc je ne fais peut-être pas quelque chose de mal, ha).
2

Doit s'étendre FragmentPagerAdapterdans votre classe d'adaptateur ViewPager.
Si vous utilisez FragmentStatePagerAdapteralors vous ne pourrez pas trouver votre Fragmentpar sonID

public static String makeFragmentName(int viewPagerId, int index) {
  return "android:switcher:" + viewPagerId + ":" + index;
}

Comment utiliser cette méthode: -

Fragment mFragment = ((FragmentActivity) getContext()).getSupportFragmentManager().findFragmentByTag(
       AppMethodUtils.makeFragmentName(mViewPager.getId(), i)
);
InterestViewFragment newFragment = (InterestViewFragment) mFragment;
mahesh_babariya
la source
2

Hé, j'ai répondu à cette question ici . Fondamentalement, vous devez remplacer

public Object instantiateItem (conteneur ViewGroup, position int)

méthode de FragmentStatePagerAdapter.

Utkarsh Saxena
la source
1

La meilleure solution consiste à utiliser l'extension que nous avons créée sur CodePath, appelée SmartFragmentStatePagerAdapter . En suivant ce guide, cela facilite considérablement la récupération des fragments et du fragment actuellement sélectionné à partir d'un ViewPager. Il gère également mieux la mémoire des fragments intégrés à l'adaptateur.

Nathan
la source
0

La manière la plus simple et la plus concise. Si tous vos fragments ViewPagersont de classes différentes, vous pouvez les récupérer et les distinguer comme suit:

public class MyActivity extends Activity
{

    @Override
    public void onAttachFragment(Fragment fragment) {
        super.onAttachFragment(fragment);
        if (fragment.getClass() == MyFragment.class) {
            mMyFragment = (MyFragment) fragment;
        }
    }

}
riwnodennyk
la source
Cela est également faux, car plusieurs fragments sont attachés lorsque vous utilisez ViewPager. il y a le fragment de page actuel, et il y en a un à sa gauche et un à sa droite. Cela permet à l'utilisateur de glisser entre eux sans avoir à les initialiser uniquement lorsque l'utilisateur les atteint.
développeur Android
0

J'ai implémenté cela facilement avec une approche un peu différente.

Ma méthode FragmentAdapter.getItem personnalisée n'a pas renvoyé MyFragment (), mais l'instance de MyFragment créée dans le constructeur FragmentAdapter.

Dans mon activité, j'ai ensuite obtenu le fragment de l'adaptateur, vérifiez s'il s'agit de l'instance du fragment nécessaire, puis converti et utilisez les méthodes nécessaires.

lxknvlk
la source
0

Créer un identifiant de ressource entier dans /values/integers.xml

<integer name="page1">1</integer>
<integer name="page2">2</integer>
<integer name="page3">3</integer>

Ensuite, dans la fonction getItem de PagerAdapter:

public Fragment getItem(int position) {

        Fragment fragment = null;

        if (position == 0) {
            fragment = FragmentOne.newInstance();
            mViewPager.setTag(R.integer.page1,fragment);

        }
        else if (position == 1) {

            fragment = FragmentTwo.newInstance();
            mViewPager.setTag(R.integer.page2,fragment);

        } else if (position == 2) {

            fragment = FragmentThree.newInstance();
            mViewPager.setTag(R.integer.page3,fragment);

        }

        return fragment;
        }

Ensuite, dans l'activité, écrivez cette fonction pour obtenir la référence du fragment:

private Fragment getFragmentByPosition(int position) {
    Fragment fragment = null;

    switch (position) {
        case 0:
            fragment = (Fragment) mViewPager.getTag(R.integer.page1);
            break;

        case 1:

            fragment = (Fragment) mViewPager.getTag(R.integer.page2);
            break;

        case 2:
            fragment = (Fragment) mViewPager.getTag(R.integer.page3);
            break;
            }

            return fragment;
    }

Obtenez la référence du fragment en appelant la fonction ci-dessus, puis convertissez-la en votre fragment personnalisé:

Fragment fragment = getFragmentByPosition(position);

        if (fragment != null) {
                    FragmentOne fragmentOne = (FragmentOne) fragment;
                    }
user2574090
la source
0

Un moyen facile d'itérer sur des fragments dans le gestionnaire de fragments. Trouvez le viewpager, qui a l'argument position de section, placé dans public PlaceholderFragment statique newInstance (int sectionNumber) .

public PlaceholderFragment getFragmentByPosition(Integer pos){
    for(Fragment f:getChildFragmentManager().getFragments()){
        if(f.getId()==R.id.viewpager && f.getArguments().getInt("SECTNUM") - 1 == pos) {
            return (PlaceholderFragment) f;
        }
    }
    return null;
}
Evgeny
la source
0

En fragment

public int getArgument(){
   return mPage;
{
public void update(){

}

In FragmentActivity

List<Fragment> fragments = getSupportFragmentManager().getFragments();
for(Fragment f:fragments){
    if((f instanceof PageFragment)&&(!f.isDetached())){
          PageFragment pf = (PageFragment)f;   
          if(pf.getArgument()==pager.getCurrentItem())pf.update();
    }
}
Mark Zhuravlyov
la source
0

dans TabLayout, il existe plusieurs onglets pour Fragment. vous pouvez trouver le fragment par Tag en utilisant l'index du fragment.

Par exemple. l'index pour Fragment1 est 0, donc dans la findFragmentByTag()méthode, passez la balise pour le Viewpager.Après avoir utilisé fragmentTransaction, vous pouvez ajouter, remplacer le fragment.

String tag = "android:switcher:" + R.id.viewPager + ":" + 0; Fragment1 f = (Fragment1) getSupportFragmentManager().findFragmentByTag(tag);

SUMIT MONAPARA
la source
-1

Ok pour l'adaptateur FragmentStatePagerAdapter je finance une solution:

dans votre FragmentActivité:

ActionBar mActionBar = getSupportActionBar(); 
mActionBar.addTab(mActionBar.newTab().setText("TAB1").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment1.class.getName())));
mActionBar.addTab(mActionBar.newTab().setText("TAB2").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment2.class.getName())));
mActionBar.addTab(mActionBar.newTab().setText("TAB3").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment3.class.getName())));

viewPager = (STViewPager) super.findViewById(R.id.viewpager);
mPagerAdapter = new MyPagerAdapter(getSupportFragmentManager(), mActionBar);
viewPager.setAdapter(this.mPagerAdapter);

et créez une méthode dans votre classe FragmentActivity - Pour que cette méthode vous donne accès à votre Fragment, il vous suffit de lui donner la position du fragment que vous voulez:

public Fragment getActiveFragment(int position) {
String name = MyPagerAdapter.makeFragmentName(position);
return getSupportFragmentManager().findFragmentByTag(name);
}

dans votre adaptateur:

public class MyPagerAdapter extends FragmentStatePagerAdapter {

private final ActionBar actionBar;
private final FragmentManager fragmentManager;

public MyPagerAdapter(FragmentManager fragmentManager, com.actionbarsherlock.app.ActionBarActionBar mActionBar) {super(fragmentManager);
this.actionBar = mActionBar;
this.fragmentManager = fragmentManager;
}

@Override
public Fragment getItem(int position) {
getSupportFragmentManager().beginTransaction().add(mTchatDetailsFragment, makeFragmentName(position)).commit();
return (Fragment)this.actionBar.getTabAt(position);
}

@Override
public int getCount() {
return this.actionBar.getTabCount();
}

@Override
public CharSequence getPageTitle(int position) {
return this.actionBar.getTabAt(position).getText();
}

private static String makeFragmentName(int viewId, int index) {
return "android:fragment:" + index;
}

}
douarbou
la source
-1
Fragment yourFragment = yourviewpageradapter.getItem(int index);

indexest la place du fragment dans l'adaptateur comme vous l'avez ajouté en fragment1premier afin de récupérer le fragment1passage indexà 0 et ainsi de suite pour le repos

Vishnu Prasad
la source