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 Fragment
du 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.
Fragment
dansWeakReference
de vous garantir ne pas empêcher un fragment d'être détruit ordures collectées? Semble juste la bonne chose à faire ...MyPagerAdapter
est détruit en raison du cycle de vie (c'est-à-dire en rotation), ne sera pasregisterdFragments
perdu? Est-ce que leActivity
/Fragment
utilisantMyPagerAdapter
doivent enregistrer dansonSaveInstanceState
et alors besoin de le mettre à jour avec la nouvelleFragmentManager
ref?getItem
ne sera pas appelé à nouveau lors de la rotation (pour les frags déjà créés), car leFragmentManager
restaure les états duFragments
contenu dans le pager. SiinstantiateItem
est appelé lorsque chacunFragment
est 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.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,
FragmentPagerAdapter
voir ci-dessous. Si celaFragmentStatePagerAdapter
vaut 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()
appelSparseArray
ouMap
getItem
n'est appelé que la première fois qu'une page est défilée vers (ou obtenue si votreViewPager.setOffscreenPageLimit(x)
> 0) dans leViewPager
, si l'hébergementActivity
/Fragment
est tué ou redémarré, alors l'interneSpaseArray
sera effacé lorsque le FragmentPagerActivity personnalisé est recréé, mais en coulisses le ViewPagers fragments internes seront recréés etgetItem
seront 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 viaFragmentManager.getFragment()
etputFragment
mais cela commence à devenir IMHO désordonné.Mauvais: créez votre propre identifiant de balise correspondant à ce qui est utilisé sous le capot
FragmentPagerAdapter
et utilisez-le pour récupérer les fragments de page de laFragmentManager
ViewPager
cela pourrait changer à tout moment ou pour toute version du système d'exploitation.La méthode recréée pour cette solution est
UN CHEMIN HEUREUX:
ViewPager.instantiateItem()
Une approche similaire à celle
getItem()
ci-dessus mais sans rupture de cycle de vie consiste à s'y connecter auinstantiateItem()
lieu degetItem()
car la première sera appelée à chaque fois que l'index est créé / accédé. Voir cette réponseUN CHEMIN HEUREUX: Construisez le vôtre
FragmentViewPager
Construisez votre propre
FragmentViewPager
classe à 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.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
FragmentPagerAdapter
ou 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.Il s'agit d'une solution simple qui résout les problèmes des deux autres solutions trouvées partout sur le Web
la source
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.getItemId(pos)
intérieurFragmentStatePagerAdapter
Ajoutez les méthodes suivantes à votre FragmentPagerAdapter:
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.
la source
Une autre solution simple:
la source
setPrimaryItem()
on l'appelle aprèsViewPager.OnPageChangeListener#onPageSelected()
je ne peux pas l'utiliser :-(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
Fragment
de mesViewPager
. Dans votreActivity
ou enFragment
maintenant leViewPager
, vous pouvez utiliser ce code pour parcourir chaqueFragment
contenu.Si vous connaissez la position de votre
Fragment
dans leViewPager
, vous pouvez simplement appelergetItem(knownPosition)
.Si vous ne connaissez pas la position de votre
Fragment
dans leViewPager
, vous pouvez demander à vos enfants d'Fragments
implémenter une interface avec une méthode commegetUniqueId()
, et de l'utiliser pour les différencier. Ou vous pouvez parcourir toutFragments
et vérifier le type de classe, tel queif(viewPagerFragment instanceof FragmentClassYouWant)
!!! ÉDITER !!!
J'ai découvert que
getItem
seulement est appelé par unFragmentPagerAdapter
lorsque chacunFragment
doit être créé la première fois , après cela, il semble que leFragments
sont recyclés à l'aide duFragmentManager
. De cette façon, de nombreuses implémentations deFragmentPagerAdapter
create newFragment
s ingetItem
. En utilisant ma méthode ci-dessus, cela signifie que nous créerons de nouveauxFragment
s à chaquegetItem
appel lorsque nous parcourons tous les éléments duFragmentPagerAdapter
. Pour cette raison, j'ai trouvé une meilleure approche, en utilisant leFragmentManager
pour obtenir chacun à laFragment
place (en utilisant la réponse acceptée). Il s'agit d'une solution plus complète qui fonctionne bien pour moi.Et vous aurez besoin de cette méthode.
la source
ViewPager
lui-même définit ces balises. Cette solution est fragile car elle repose sur la connaissance de la convention de nommage "cachée" duViewPager
. 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).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.
la source
la source
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:
alors cela peut être appelé:
alors je pourrais le jeter dans une instruction if qui ne fonctionnerait que si elle était sur le bon fragment
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é.
la source
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.
la source
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.
la source
FragmentPagerAdapter est la fabrique des fragments. Pour trouver un fragment basé sur sa position s'il est encore en mémoire, utilisez ceci:
Exemple de code pour l'API de support v4.
la source
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'unFragment
hébergé à l'intérieurViewPager
. Si vous souhaitez mettre à jour certaines données à l'intérieur,Fragment
utilisez cette approche: Mettre à jour ViewPager dynamiquement?La clé est de définir de nouvelles données à l'intérieur
Adaper
et d'appelernotifyDataSetChanged()
qui à leur tour appelleragetItemPosition()
, vous transmettant une référenceFragment
et 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.la source
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 appelezadapter.notifyDataSetChanged()
qui à son tour appelleragetItemPosition()
de votre adaptateur en passant la référence de votreFragment
s. Vous pouvez voir une implémentation complète en action ici stackoverflow.com/questions/19891828/…Fragment
mais comment obtenir une référence est discutable. D'autres solutions obtiennent des références enFragmentManager
utilisant une chaîne similaire à"android:switcher:"+id
ou en revenantPOSITION_NONE
degetItemosition()
provoquer la recréation de tous les fragments.Doit s'étendre
FragmentPagerAdapter
dans votre classe d'adaptateur ViewPager.Si vous utilisez
FragmentStatePagerAdapter
alors vous ne pourrez pas trouver votreFragment
par sonID
Comment utiliser cette méthode: -
la source
Hé, j'ai répondu à cette question ici . Fondamentalement, vous devez remplacer
méthode de FragmentStatePagerAdapter.
la source
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.
la source
La manière la plus simple et la plus concise. Si tous vos fragments
ViewPager
sont de classes différentes, vous pouvez les récupérer et les distinguer comme suit:la source
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.
la source
Créer un identifiant de ressource entier dans /values/integers.xml
Ensuite, dans la fonction getItem de PagerAdapter:
Ensuite, dans l'activité, écrivez cette fonction pour obtenir la référence du fragment:
Obtenez la référence du fragment en appelant la fonction ci-dessus, puis convertissez-la en votre fragment personnalisé:
la source
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) .
la source
En fragment
In FragmentActivity
la source
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);
la source
Ok pour l'adaptateur
FragmentStatePagerAdapter
je finance une solution:dans votre FragmentActivité:
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:
dans votre adaptateur:
la source
index
est la place du fragment dans l'adaptateur comme vous l'avez ajouté enfragment1
premier afin de récupérer lefragment1
passageindex
à 0 et ainsi de suite pour le reposla source