Mise à jour ViewPager dynamiquement?
Je ne peux pas mettre à jour le contenu dans ViewPager.
Qu'est-ce que l'utilisation correcte des méthodes instantiateItem() et getItem() dans FragmentPagerAdapter classe?
J'ai été en utilisant seulement getItem() pour instancier et de retour de mes fragments:
@Override
public Fragment getItem(int position) {
return new MyFragment(context, paramters);
}
Cela a bien fonctionné. Sauf que je ne peut pas changer le contenu.
J'ai donc trouvé ceci: ViewPager PagerAdapter pas la mise à jour de la Vue
"Mon approche est d'utiliser la setTag() méthode pour n'importe quel autre vue dans le instantiateItem() la méthode"
Maintenant, je veux mettre en œuvre instantiateItem() pour le faire. Mais je ne sais pas ce que j'ai à retourner (le type de l'Objet) et quel est le rapport avec getItem(int position)?
J'ai lu le référence:
public abstract Fragment getItem (int position)
Retour le Fragment associé à une position spécifiée.
Objet public instantiateItem (ViewGroup container, int position)
Créer la page pour la position donnée. La carte est responsable de l'ajout de la vue vers le conteneur est donnée ici, bien qu'il ne doit s'en assurer par le temps, elle retourne de finishUpdate(ViewGroup).
Paramètresrécipient contenant de la Vue dans laquelle la page sera affichée.
la position la position de La page pour être instancié.Retourne
Retourne un Objet représentant la nouvelle page. Ce ne doit pas être Vue, mais peut être un autre conteneur de la page.
mais je ne comprends toujours pas.
Voici mon code. Je suis d'utilisation d'un support package v4.
ViewPagerTest
public class ViewPagerTest extends FragmentActivity {
private ViewPager pager;
private MyFragmentAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pager1);
pager = (ViewPager)findViewById(R.id.slider);
String[] data = {"page1", "page2", "page3", "page4", "page5", "page6"};
adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
pager.setAdapter(adapter);
((Button)findViewById(R.id.button)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
reload();
}
});
}
private void reload() {
String[] data = {"changed1", "changed2", "changed3", "changed4", "changed5", "changed6"};
//adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
adapter.setData(data);
adapter.notifyDataSetChanged();
pager.invalidate();
//pager.setCurrentItem(0);
}
}
MyFragmentAdapter
class MyFragmentAdapter extends FragmentPagerAdapter {
private int slideCount;
private Context context;
private String[] data;
public MyFragmentAdapter(FragmentManager fm, int slideCount, Context context, String[] data) {
super(fm);
this.slideCount = slideCount;
this.context = context;
this.data = data;
}
@Override
public Fragment getItem(int position) {
return new MyFragment(data[position], context);
}
@Override
public int getCount() {
return slideCount;
}
public void setData(String[] data) {
this.data = data;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
MyFragment
public final class MyFragment extends Fragment {
private String text;
public MyFragment(String text, Context context) {
this.text = text;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.slide, null);
((TextView)view.findViewById(R.id.text)).setText(text);
return view;
}
}
Ici est aussi quelqu'un avec un problème similaire, pas de réponses
http://www.mail-archive.com/[email protected]/msg200477.html
- Pour obtenir une meilleure compréhension des composants impliqués, il pourrait aider à lire mon tutoriel sur l'un des onglets de ViewPager avec séparés en arrière histoire de la navigation. Il est livré avec un exemple de travail sur GitHub et ressources supplémentaires: medium.com/@nilan/...
- obtenu quelques stackoverflow.com/questions/40149039/...
- Vous pouvez le vérifier sur ce exemple sur GitHub. J'espère que cet exemple vous permet de.
- La bonne solution la plus simple: stackoverflow.com/a/35450575/2162226
Vous devez vous connecter pour publier un commentaire.
Lors de l'utilisation de FragmentPagerAdapter ou FragmentStatePagerAdapter, il est préférable de traiter uniquement avec
getItem()
et ne pas les toucherinstantiateItem()
à tous. LeinstantiateItem()
-destroyItem()
-isViewFromObject()
interface sur PagerAdapter est un moindre niveau de l'interface que FragmentPagerAdapter utilise pour mettre en œuvre le plus simplegetItem()
interface.Avant d'entrer dans cela, je me dois de préciser que
Une version antérieure de cette réponse fait l'erreur d'utiliser des FragmentPagerAdapter pour son exemple - qui ne fonctionne pas parce que FragmentPagerAdapter jamais détruit un fragment après qu'il a été présenté la première fois.
Je ne recommande pas le
setTag()
etfindViewWithTag()
solution de contournement fournie dans le post que vous avez lié. Comme vous l'avez découvert, à l'aide desetTag()
etfindViewWithTag()
ne fonctionne pas avec les fragments, il n'est donc pas un bon match.La bonne solution est de remplacer
getItemPosition()
. LorsquenotifyDataSetChanged()
est appelé, ViewPager appelsgetItemPosition()
sur tous les éléments de sa carte pour voir si ils ont besoin d'être déplacé vers un autre poste ou à retirer.Par défaut,
getItemPosition()
retournePOSITION_UNCHANGED
, ce qui signifie, "Cet objet est très bien où il est, ne pas détruire ou de le supprimer." De retourPOSITION_NONE
résout le problème en disant: "Cet objet n'est plus un point je suis d'affichage, de le supprimer." Donc, il a pour effet de supprimer et de recréer tous les articles dans votre carte.C'est complètement légitime fixer! Cette correction fait notifyDataSetChanged se comporter comme un simple Adaptateur sans afficher de recyclage. Si vous appliquez ce correctif et la performance est satisfaisante, vous êtes hors de la course. Le travail est accompli.
Si vous avez besoin de meilleures performances, vous pouvez utiliser un amateur de
getItemPosition()
mise en œuvre. Voici un exemple pour un pager la création de fragments hors d'une liste de chaînes de caractères:Avec cette mise en œuvre, seuls des fragments de l'affichage de nouveaux titres seront affichées. Tous les fragments de l'affichage des titres qui sont encore dans la liste, au lieu d'être déplacé autour de leur nouvelle position dans la liste, et des fragments avec des titres qui ne sont plus dans la liste, sera détruit.
Que si le fragment n'a pas été recréé, mais doit être mis à jour de toute façon? Mises à jour d'un fragment de vie sont mieux gérées par le fragment lui-même. C'est l'avantage d'avoir un fragment, après tout c'est son propre contrôleur. Un fragment peut ajouter un écouteur ou un observateur à un autre objet dans
onCreate()
, et retirez-la ensuite dansonDestroy()
, ainsi, la gestion des mises à jour de lui-même. Vous n'avez pas à mettre tout le code de mise à jour à l'intérieur degetItem()
comme vous le faites dans un adaptateur pour un contrôle ListView ou d'autres AdapterView types.Une dernière chose - juste parce que FragmentPagerAdapter ne pas détruire un fragment ne veut pas dire que getItemPosition est complètement inutile dans un FragmentPagerAdapter. Vous pouvez toujours utiliser cette fonction de rappel pour réorganiser vos fragments en les ViewPager. Il ne sera jamais à les supprimer complètement de la FragmentManager, si.
FragmentStatePageAdapter
et lagetItemPosition
, mais pas les deux ensemble. Essayer travaille ensemble, je vous remercie!FragmentPagerAdapter
àFragmentStatePageAdapter
, ça fonctionne :'( tu m'as sauvé la vie !!!MyFragment
et où le savoir, merci!FragmentStatePagerAdapter
, je peux voir qu'il supprime mon fragment et de la création de la nouvelle instance. Mais la nouvelle instance reçoit un Bundle savedInstanceState avec l'état d'un vieux fragment. Comment puis-je détruire complètement le fragment de Bundle est null lors de la création de nouveau?Au lieu de retourner
POSITION_NONE
degetItemPosition()
et causant une vue complète de loisirs, faites ceci:Vos fragments devraient mettre en œuvre
UpdateableFragment
interface:et de l'interface:
Votre classe de données:
Fragment
dynamiquement, regardez: stackoverflow.com/questions/19891828/...d page on refreshes the 1-st page only after swiping pages? thw 2
d page est toujours vide. merciUpdateData
qui peut alors être utilisé pour rejeter mise à jour à l'intérieur de fragment.BaseFragment
ou quoi que ce soit. De toute façon mis à jour ma réponse pour une classe.pour ceux qui font toujours face au même problème que j'ai rencontrés avant, quand j'ai un ViewPager avec 7 fragments. la valeur par défaut pour ces fragments pour charger le contenu anglais à partir de l'api de service, mais le problème ici que je veux changer la langue dans les paramètres de l'activité et après l'arrivée
les paramètres de l'activité, je veux ViewPager en activité principale de rafraîchir les fragments pour correspondre à la sélection de la langue de l'utilisateur et de charger les contenus en arabe si l'utilisateur a choisi l'arabe ici ce que j'ai fait de travailler à partir de la première fois
1 - Vous devez utiliser FragmentStatePagerAdapter comme mentionné ci-dessus.
2-sur mainActivity je remplace la onResume et a la suite de
3-je surdéfini la getItemPosition() dans mPagerAdapter et faire revenir POSITION_NONE.
fonctionne comme un charme
J'ai rencontré ce problème et enfin résolu aujourd'hui, donc j'écris ce que j'ai appris et j'espère que c'est utile pour quelqu'un qui est nouveau pour Android
ViewPager
et de mise à jour comme je le fais. Je suis en utilisantFragmentStatePagerAdapter
de l'API de niveau 17 et actuellement seulement 2 fragments. Je pense qu'il doit y avoir quelque chose de pas correct, merci de me corriger, merci.De données sérialisées doit être chargé en mémoire. Cela peut être fait à l'aide d'un
CursorLoader
/AsyncTask
/Thread
. Si il est automatiquement chargé dépend de votre code. Si vous utilisez unCursorLoader
, il est chargé automatiquement puisqu'il y est inscrit les données de l'observateur.Après l'appel de
viewpager.setAdapter(pageradapter)
, la cartegetCount()
est constamment appelé à construire des fragments. Donc, si des données est en cours de chargement,getCount()
peut retourner 0, donc vous n'avez pas besoin de créer dummy fragments de données non montrées.Une fois les données chargées, la carte ne sera pas construire des fragments automatiquement depuis
getCount()
est toujours de 0, on peut donc définir le chargé le numéro des données retournées pargetCount()
, puis d'appeler la cartenotifyDataSetChanged()
.ViewPager
de commencer à créer des fragments (juste les 2 premiers fragments) par les données dans la mémoire. C'est fait avantnotifyDataSetChanged()
est retourné. Puis leViewPager
a le droit de fragments dont vous avez besoin.Si les données dans la base de données et la mémoire sont à la fois mis à jour (write through), ou tout simplement les données dans la mémoire est mise à jour (write back), ou uniquement les données dans la base de données est mise à jour. Dans les deux derniers cas, si les données ne sont pas automatiquement chargés à partir de la base de données en mémoire (comme mentionné ci-dessus).
Le
ViewPager
et pager adaptateur simplement de traiter des données en mémoire.Ainsi, lorsque les données dans la mémoire est mise à jour, il suffit d'appeler la carte
notifyDataSetChanged()
. Depuis le fragment est déjà créé, la carteonItemPosition()
sera appelée avantnotifyDataSetChanged()
retourne. Rien ne doit être fait dansgetItemPosition()
. Ensuite, les données sont mises à jour.notifyDataSetChanged()
puis juste mis à jour automatiquement, parce que le fragment(avec chartview) je vais actualiser lui-même. si ce n'est pas, comme statique fragment, je vais devoir appeleronItemPositon()
et retournePOSITION_NONE
désoléEssayer
destroyDrawingCache()
sur ViewPager aprèsnotifyDataSetChanged()
dans votre code.Fragments
de mon point de vue pager. Donc, je vous remercie!Après des heures de frustration en essayant toutes les solutions ci-dessus afin de surmonter ce problème et tente également de nombreuses solutions sur d'autres questions similaires comme cette, cette et cette qui ont tous ÉCHOUÉ avec moi à résoudre ce problème et de faire le
ViewPager
à détruire l'ancienFragment
et de remplir lepager
avec la nouvelleFragment
s. J'ai résolu le problème comme suit:1) Faire la
ViewPager
classe étendFragmentPagerAdapter
comme suit:2) Créer un poste pour la
ViewPager
qui stockent lestitle
et lafragment
comme suit:3) Faire le constructeur de la
ViewPager
prendre monFragmentManager
exemple, de le stocker dans monclass
comme suit:4) Créer une méthode de re-définir la
adapter
de données avec les nouvelles données par la suppression de tous les précédentsfragment
de lafragmentManager
lui-même directement faire lesadapter
pour définir le nouveaufragment
de la nouvelle liste de nouveau de la manière suivante:5) à Partir du conteneur
Activity
ouFragment
ne pas ré-initialiser la carte avec les nouvelles données. Définir les nouvelles données par le biais de la méthodesetPagerItems
avec les nouvelles données de la manière suivante:J'espère que cela aide.
Pour une raison quelconque, aucune des réponses travaillé pour moi, donc j'ai dû remplacer la restoreState méthode sans appel à super dans mon fragmentStatePagerAdapter. Code:
J'ai légèrement modifié la solution apportée par le projet de Loi de Phillips pour répondre à mes besoins
de sorte que le
getItemPosition()
retournePOSITION_NONE
uniquement pour les fragments qui sont actuellement dans laFragmentManager
quandgetItemPosition
est appelé.(Notez que cette
FragmentStatePager
et laViewPager
qui lui sont associés sont contenues dans un Fragment non pas dans une Activité)J'ai eu un problème similaire, mais ne veulent pas de la confiance sur les solutions existantes (codé en dur des noms de balises, etc.) et je n'arrivais pas à M-WaJeEh la solution de travail pour moi. Voici ma solution:
Je garde les références à l'fragments créés dans getItem dans un tableau. Cela fonctionne très bien tant que l'activité n'est pas détruit à cause de configurationChange ou le manque de mémoire ou quoi (--> au retour à l'activité, des fragments de retourner dans leur dernier état, sans getItem' être appelé de nouveau et donc sans mise à jour du tableau).
Pour éviter ce problème, j'ai mis en œuvre instantiateItem(ViewGroup, int) et de mettre à jour mon tableau, comme ceci:
Donc, d'un côté, je suis heureux que j'ai trouvé une solution qui fonctionne pour moi et je voulais le partager avec vous, mais je voulais aussi demander si quelqu'un d'autre a essayé quelque chose de similaire et s'il existe une raison pourquoi je ne devrais pas faire comme ça? Jusqu'à présent, il fonctionne très bien pour moi...
myFragments
danspublic void destroyItem(ViewGroup container, int position, Object object)
ainsi afin de ne pas attraper un rassis fragement de référence.- Je utiliser EventBus bibliothèque pour mettre à jour
Fragment
contenu dansViewPager
. La logique est simple, tout comme document de EventBus comment faire. Il n'est pas besoin de contrôle de laFragmentPagerAdapter
instance. Le code est ici:1: Définir les événements
Définir le message qui est nécessaire pour la mise à jour.
2.Préparer les abonnés
Écrire de code ci-dessous dans le Fragment qui est nécessaire mise à jour.
3.Événements Post
Écrire de code ci-dessous dans d'autres
Activity
ou d'autresFragment
qui doit mettre à jour le paramètreSi vous souhaitez utiliser FragmentStatePagerAdapter, veuillez jeter un oeil à https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby=&sort=&id=37990.
Il y a des problèmes avec FragmentStatePagerAdapter qui peuvent ou non de la difficulté à votre cas d'utilisation.
Aussi, le lien a peu de solutions trop..quelques susceptible de répondre à votre exigence.
J'ai vécu le même problème et j'ai cherché trop de temps. Toute réponse donnée dans stackoverflow ou par l'intermédiaire de google n'était pas de solution pour mon problème. Mon problème a été facile. J'ai une liste, je montre cette liste avec viewpager. Quand j'ajoute un élément nouveau à la tête de la liste et j'ai actualiser la viewpager rien changé. Ma solution finale a été très facile, n'importe qui peut utiliser. Lorsqu'un nouvel élément ajouté à la liste et souhaitez actualiser la liste. Tout d'abord définir viewpager adaptateur null puis recréer la carte et je me elle à viewpager.
Assurez-vous que votre adaptateur doit s'étendre FragmentStatePagerAdapter
J'avais essayé beaucoup d'approches différentes, aucun vraiment résoudre mon problème. Ci-dessous sont la façon dont je le résoudre avec un mélange de solutions fournies par vous tous. Merci à tous.
Je ne veux me rafraîchir la page 0 après onResume().
Dans mon FragmentsMain, il est public integer "page", qui peut me dire si c'est la page que je veux actualiser.
Je sais suis en retard pour la Fête. J'ai résolu le problème en appelant
TabLayout#setupWithViewPager(myViewPager);
juste aprèsFragmentPagerAdapter#notifyDataSetChanged();
Cette solution ne fonctionne pas pour tout le monde, mais dans mon cas, chaque Fragment dans mon ViewPager est une classe différente, et un seul d'entre eux jamais existé à un moment.
Avec cette contrainte, cette solution est sûr et devrait être utilisée dans la production.
Si vous avez plusieurs versions d'un même fragment, vous pouvez utiliser la même stratégie pour l'appel de méthodes sur ces fragments pour déterminer si c'est la fragment que vous souhaitez mettre à jour.
Cela peut être de l'aide à quelqu'un, dans mon cas, lors de l'insertion d'une nouvelle page de la vue pager a été demandé pour le poste d'un fragment de deux fois, mais ne pas demander la position de l'élément nouveau, provoquant un comportement incorrect et des données de l'affichage.
Copier le source pour pour FragmentStatePagerAdapter (semble ne pas avoir été mis à jour depuis des lustres).
Remplacer notifyDataSetChanged()
Ajouter une vérification générale de destroyItem() pour éviter les accidents:
Je suis passé par toutes les réponses ci-dessus et un certain nombre d'autres postes, mais ne pouvait toujours pas trouver quelque chose qui a fonctionné pour moi (avec les différentes fragment de types avec l'ajout dynamique et la suppression des tabulations). FWIW approche suivante est ce qui a fonctionné pour moi (au cas où quelqu'un d'autre a les mêmes problèmes).
Utilisation FragmentStatePagerAdapter au lieu de FragmentPagerAdapter
si vous souhaitez recréer ou de recharger fragment sur l'indice de base
Par exemple, si vous souhaitez recharger fragment d'autres que FirstFragment, vous pouvez vérifier instance et de retour de position comme ceci
Voici ma mise en œuvre qui intègre l'info de @Bill Phillips
On obtient fragment de la mise en cache la plupart du temps, sauf lorsque les données ont changé. Simple, et semble bien fonctionner.
MyFragmentStatePagerAdapter.java
MyActivity.java