Mettre à jour ViewPager dynamiquement?

Je ne peux pas mettre à jour le contenu dans ViewPager.

une question: Quelle est la relation et l'usage correct des méthodes instantiateItem() et getItem() dans la classe FragmentPagerAdapter?

j'utilisais seulement getItem () pour instancier et rendre mes fragments:

@Override
public Fragment getItem(int position) {
    return new MyFragment(context, paramters);
}

cela a bien fonctionné (mais comme dit Je ne peux pas changer le contenu).

donc j'ai trouvé ceci: ViewPager PagerAdapter pas mise à jour de la vue

en particulier un dans lequel il est parlé de méthode instantiateItem ():

"mon approche est d'utiliser la méthode setTag() pour n'importe quelle vue instanciée dans la méthode instantiateItem () "

donc maintenant je veux implémenter instantiateItem() pour le faire. Mais je ne sais pas ce que je dois y retourner (le retour est Objet) et quelle est la relation avec getItem(position int)?

J'utilise getItem pour instancier le Fragment, c'est mal? Mais alors je dois mettre les fragments en instance variable, ou ne pas implémenter getItem() du tout...? Je ne comprends juste pas.

j'ai essayé de lire le référence :

  • Public abstract Fragment getItem (position int)

    renvoie le Fragment associé avec une position spécifiée.

  • public Object instantiateItem (ViewGroup container, int position)

    créer la page pour la position donnée. L'adaptateur est responsable d'ajouter la vue au conteneur donné ici, bien qu'il ne doive s'assurer que cela est fait avant le retour de finishUpdate(ViewGroup). Paramètres

    conteneur la vue contenant dans laquelle la page sera illustré. positionnez la position de la page à instancier.

    retourne

    renvoie 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 comment ils sont liés et ce que je dois faire.

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;
    }
}

voici aussi quelqu'un qui a un problème similaire, sans réponse...

http://www.mail-archive.com/android-developers@googlegroups.com/msg200477.html

278
demandé sur Community 2012-06-01 15:38:46

18 réponses

lors de L'utilisation FragmentPagerAdapter ou FragmentStatePagerAdapter, il est préférable de traiter uniquement avec getItem() et ne pas toucher instantiateItem() du tout. Les instantiateItem() - destroyItem() - isViewFromObject() l'interface sur PagerAdapter est une interface de niveau inférieur que FragmentPagerAdapter utilise pour implémenter l'interface getItem() beaucoup plus simple.

avant d'entrer dans ce, je dois préciser que

si vous voulez basculer les fragments qui sont affichés, vous devez éviter FragmentPagerAdapter et l'utilisation FragmentStatePagerAdapter.

une version antérieure de cette réponse a fait l'erreur d'utiliser FragmentPagerAdapter pour son exemple - qui ne fonctionnera pas parce que FragmentPagerAdapter ne détruit jamais un fragment après qu'il a été affiché la première fois.

Je ne recommande pas la solution setTag() et findViewWithTag() fournis dans le post lié. Comme vous l'avez découvert, utiliser setTag() et findViewWithTag() ne fonctionne pas avec les fragments, donc ce n'est pas une bonne correspondance.

la bonne solution est de remplacer getItemPosition() . Quand notifyDataSetChanged() est appelé, ViewPager appelle getItemPosition() sur tous les articles de son adaptateur pour voir s'ils doivent être déplacés à une position différente ou enlevés.

par défaut, getItemPosition() renvoie POSITION_UNCHANGED , ce qui signifie, l'objet est bien là où il est, ne le détruisez pas ou l'enlever."Returning POSITION_NONE corrige le problème en disant," Cet objet n'est plus un objet que j'affiche, supprimez-le."Il a donc pour effet d'enlever et de recréer chaque élément de votre adaptateur.

c'est une solution tout à fait légitime! Ce correctif permet à notifyDataSetChanged de se comporter comme un adaptateur régulier sans recyclage de vue. Si vous mettez en œuvre ce correctif et la performance est satisfaisante, vous allez à la course. Le travail est accompli.

si vous avez besoin de meilleures performances, vous pouvez utiliser un fancier getItemPosition() mise en œuvre. Voici un exemple pour un pager créant des fragments à partir d'une liste de chaînes:

ViewPager pager = /* get my ViewPager */;
// assume this actually has stuff in it
final ArrayList<String> titles = new ArrayList<String>();

FragmentManager fm = getSupportFragmentManager();
pager.setAdapter(new FragmentStatePagerAdapter(fm) {
    public int getCount() {
        return titles.size();
    }

    public Fragment getItem(int position) {
        MyFragment fragment = new MyFragment();
        fragment.setTitle(titles.get(position));
        return fragment;
    }

    public int getItemPosition(Object item) {
        MyFragment fragment = (MyFragment)item;
        String title = fragment.getTitle();
        int position = titles.indexOf(title);

        if (position >= 0) {
            return position;
        } else {
            return POSITION_NONE;
        }
    }
});

avec cette implémentation, seuls les fragments affichant de nouveaux titres seront affichés. Tous les fragments affichant des titres qui sont encore dans la liste seront plutôt déplacés à leur nouvelle position dans la liste, et les fragments avec des titres qui ne sont pas plus dans la liste, sera détruit.

Que faire si le fragment n'a pas été recréé, mais doit être mis à jour de toute façon? Les mises à jour d'un fragment vivant 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 auditeur ou un observateur à un autre objet dans onCreate() , puis le supprimer dans onDestroy() , gérant ainsi les mises à jour elle-même. Vous n'avez pas à mettre tout le code de mise à jour à l'intérieur de getItem() comme vous le faites dans un adaptateur pour un ListView ou D'autres types D'Adaptateur.

une dernière chose - ce n'est pas parce que FragmentPagerAdapter ne détruit pas un fragment que getitempposition est complètement inutile dans un FragmentPagerAdapter. Vous pouvez toujours utiliser ce callback pour réordonner vos fragments dans le ViewPager. Il ne les enlèvera jamais complètement du FragmentManager, cependant.

554
répondu Bill Phillips 2017-08-03 16:28:00

au lieu de retourner POSITION_NONE de getItemPosition() et de provoquer la pleine vue Loisirs, faire ceci:

//call this method to update fragments in ViewPager dynamically
public void update(UpdateData xyzData) {
    this.updateData = xyzData;
    notifyDataSetChanged();
}

@Override
public int getItemPosition(Object object) {
    if (object instanceof UpdateableFragment) {
        ((UpdateableFragment) object).update(updateData);
    }
    //don't return POSITION_NONE, avoid fragment recreation. 
    return super.getItemPosition(object);
}

vos fragments doivent implémenter UpdateableFragment interface:

public class SomeFragment extends Fragment implements
    UpdateableFragment{

    @Override
    public void update(UpdateData xyzData) {
         // this method will be called for every fragment in viewpager
         // so check if update is for this fragment
         if(forMe(xyzData)) {
           // do whatever you want to update your UI
         }
    }
}

et l'interface:

public interface UpdateableFragment {
   public void update(UpdateData xyzData);
}

votre classe de données:

public class UpdateData {
    //whatever you want here
}
126
répondu M-WaJeEh 2017-05-16 08:09:14

pour ceux qui font encore face au même problème que j'ai rencontré avant quand j'ai un ViewPager avec 7 fragments. le défaut pour ces fragments de charger le contenu anglais du service api, mais le problème ici que je veux changer la langue de l'activité paramètres et après finition paramètres activité je veux ViewPager dans l'activité principale pour rafraîchir les fragments pour correspondre à la sélection de langue de l'utilisateur et charger le contenu arabe si l'Utilisateur a choisi l'Arabe ici ce que j'ai fait pour travailler de la première fois

1 - vous devez utiliser FragmentStatePagerAdapter comme mentionné ci-dessus.

2-sur mainActivity je remplace la onResume et fait la suite de

 if (!(mPagerAdapter == null)) {
mPagerAdapter.notifyDataSetChanged();
}

3-je surdéfini la getItemPosition() dans mPagerAdapter et faire revenir POSITION_NONE.

 @Override
   public int getItemPosition(Object object) {
     return POSITION_NONE;
    }

fonctionne comme le charme

15
répondu Ziad Gholmish 2017-11-23 11:34:00

j'ai rencontré ce problème et finalement résolu aujourd'hui, donc je note ce que j'ai appris et j'espère qu'il est utile pour quelqu'un qui est nouveau à Android ViewPager et mettre à jour comme je le fais. J'utilise FragmentStatePagerAdapter au niveau 17 de L'API et je n'ai actuellement que 2 fragments. Je pense qu'il doit y avoir quelque chose qui n'est pas correct, s'il vous plaît, corrigez-moi, merci. enter image description here

  1. les données sérialisées doivent être chargées en mémoire. Cela peut être fait en utilisant un CursorLoader / AsyncTask / Thread . Que ce soit automatiquement chargé dépend de votre code. Si vous utilisez un CursorLoader , il est auto-chargé car il y a un observateur de données enregistré.

  2. après avoir appelé viewpager.setAdapter(pageradapter) , le getCount() de l'adaptateur est constamment appelé à construire des fragments. Donc si les données sont chargées, getCount() peut retourner 0, donc vous n'avez pas besoin de créer des fragments factices pour aucune donnée affichée.

  3. une fois les données chargées, l'adaptateur ne construira pas de fragments automatiquement car getCount() est toujours 0, nous pouvons donc définir le numéro de données chargé pour être retourné par getCount() , puis appeler notifyDataSetChanged() de l'adaptateur . ViewPager commence à créer des fragments (seulement les 2 premiers fragments) par des données en mémoire. C'est fait avant que notifyDataSetChanged() ne soit retourné. Puis le ViewPager a les bons fragments dont vous avez besoin.

  4. si les données de la base de données et de la mémoire sont à la fois mises à jour (écriture par), ou seulement des données dans la mémoire est mise à jour (écriture en retour), ou seulement des 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ées de la base de données en mémoire (comme mentionné ci-dessus). L'adaptateur ViewPager et le pager ne traitent que les données en mémoire.

  5. ainsi lorsque les données en mémoire est mis à jour, nous avons juste besoin d'appeler l'adaptateur notifyDataSetChanged() . Puisque le fragment est déjà créé, le onItemPosition() de l'adaptateur sera appelé avant le retour de notifyDataSetChanged() . Rien ne doit être fait dans getItemPosition() . Ensuite, les données sont mises à jour.

14
répondu oscarthecat 2014-06-08 22:33:44

Essayer destroyDrawingCache() sur ViewPager après notifyDataSetChanged() dans votre code.

12
répondu czaku 2013-07-19 06:09:00

après des heures de frustration tout en essayant toutes les solutions ci-dessus pour surmonter ce problème et aussi en essayant de nombreuses solutions sur d'autres questions similaires comme ce , ce et ce qui ont tous échoué avec moi pour résoudre ce problème et de faire le ViewPager pour détruire l'ancien Fragment et remplir le pager avec le nouveau Fragment s. J'ai résolu le problème comme suit:

1) faites la classe ViewPager pour étendre FragmentPagerAdapter comme suit:

 public class myPagerAdapter extends FragmentPagerAdapter {

2) créer un article pour le ViewPager qui stocke le title et le fragment comme suit:

public class PagerItem {
private String mTitle;
private Fragment mFragment;


public PagerItem(String mTitle, Fragment mFragment) {
    this.mTitle = mTitle;
    this.mFragment = mFragment;
}
public String getTitle() {
    return mTitle;
}
public Fragment getFragment() {
    return mFragment;
}
public void setTitle(String mTitle) {
    this.mTitle = mTitle;
}

public void setFragment(Fragment mFragment) {
    this.mFragment = mFragment;
}

}

3) faire le constructeur du ViewPager prendre mon FragmentManager instance pour le stocker dans mon class comme suit:

private FragmentManager mFragmentManager;
private ArrayList<PagerItem> mPagerItems;

public MyPagerAdapter(FragmentManager fragmentManager, ArrayList<PagerItem> pagerItems) {
    super(fragmentManager);
    mFragmentManager = fragmentManager;
    mPagerItems = pagerItems;
}

4) créer une méthode pour re-définir les données adapter avec les nouvelles données en supprimant tous les fragment de la fragmentManager elle-même directement pour faire le adapter pour définir le nouveau fragment de la nouvelle liste à nouveau comme suit:

public void setPagerItems(ArrayList<PagerItem> pagerItems) {
    if (mPagerItems != null)
        for (int i = 0; i < mPagerItems.size(); i++) {
            mFragmentManager.beginTransaction().remove(mPagerItems.get(i).getFragment()).commit();
        }
    mPagerItems = pagerItems;
}

5) du conteneur Activity ou Fragment ne pas ré-initialiser l'adaptateur avec le nouveau données. Définir les nouvelles données par la méthode setPagerItems avec les nouvelles données comme suit:

ArrayList<PagerItem> pagerItems = new ArrayList<PagerItem>();
    pagerItems.add(new PagerItem("Fragment1", new MyFragment1()));
    pagerItems.add(new PagerItem("Fragment2", new MyFragment2()));

    mPagerAdapter.setPagerItems(pagerItems);
    mPagerAdapter.notifyDataSetChanged();

j'espère que ça aidera.

10
répondu Sami Eltamawy 2017-05-23 12:10:32

pour une raison quelconque, aucune des réponses n'a fonctionné pour moi, donc j'ai dû outrepasser la méthode restoreState sans appeler super dans mon fragmentStatePagerAdapter. Code:

private class MyAdapter extends FragmentStatePagerAdapter {

    // [Rest of implementation]

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {}

}
7
répondu hordurh 2015-08-18 15:41:47

j'ai légèrement modifié la solution apportée par le projet de Loi de Phillips pour répondre à mes besoins

private class PagerAdapter extends FragmentStatePagerAdapter{
    Bundle oBundle;
    FragmentManager oFragmentManager;
    ArrayList<Fragment> oPooledFragments;

public PagerAdapter(FragmentManager fm) {
    super(fm);
    oFragmentManager=fm;

    }
@Override
public int getItemPosition(Object object) {

    Fragment oFragment=(Fragment)object;
    oPooledFragments=new ArrayList<>(oFragmentManager.getFragments());
    if(oPooledFragments.contains(oFragment))
        return POSITION_NONE;
    else
        return POSITION_UNCHANGED;
    } 
}

de sorte que le getItemPosition() retourne POSITION_NONE seulement pour les fragments qui sont actuellement dans le FragmentManager quand getItemPosition est appelé. (Notez que ce FragmentStatePager et le ViewPager qui lui est associé sont contenus dans un Fragment ne faisant pas partie d'une activité)

3
répondu adwait 2016-09-27 13:22:15

j'ai eu un problème similaire mais je ne veux pas faire confiance aux solutions existantes (noms d'étiquette codés, etc.) et je n'ai pas pu faire fonctionner la solution de M-WaJeEh pour moi. Voici ma solution:

je garde des références aux fragments créés dans getItem dans un tableau. Cela fonctionne très bien tant que l'activité n'est pas détruite en raison d'un changement de configuration ou d'un manque de mémoire ou autre (--> en revenant à l'activité, les fragments reviennent à leur dernier état sans que le "getItem" soit appelé à nouveau et donc sans mettre à jour le tableau).

pour éviter ce problème, j'ai implémenté instantiateItem (ViewGroup, int) et mis à jour mon tableau, comme ceci:

        @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Object o = super.instantiateItem(container, position);
        if(o instanceof FragmentX){
            myFragments[0] = (FragmentX)o;
        }else if(o instanceof FragmentY){
            myFragments[1] = (FragmentY)o;
        }else if(o instanceof FragmentZ){
            myFragments[2] = (FragmentZ)o;
        }
        return o;
    }

donc, d'un côté je suis heureux que j'ai trouvé une solution qui fonctionne pour moi et je voulais la partager avec vous, mais je voulais aussi demander si quelqu'un d'autre a essayé quelque chose de similaire et s'il y a une raison pour que je ne le fasse pas comme ça? Jusqu'à présent, il fonctionne très bien pour je...

2
répondu jpm 2013-11-06 12:00:56

si vous voulez utiliser FragmentStatePagerAdapter, s'il vous plaît 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 ne peuvent pas perturber votre utilisation.

aussi, link a peu de solutions aussi..peu conviennent à vos besoins.

1
répondu cgr 2016-02-22 08:54:14

j'ai vécu le même problème et j'ai cherché trop de temps. Toute réponse donnée dans stackoverflow ou via google n'a pas été la 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 nouvel élément à la tête de la liste et que je rafraîchis le ViewPager nothings changé. Ma solution finale était très facile à utiliser. Lorsqu'un nouvel élément ajouté à la liste et souhaitez actualiser la liste. Tout d'abord définir l'adaptateur viewpager à null puis recréer l'adaptateur et jeu de je pour viewpager.

myVPager.setAdapter(null);
myFragmentAdapter = new MyFragmentAdapter(getSupportFragmentManager(),newList);
myVPager.setAdapter(myFragmentAdapter);

assurez-vous que votre adaptateur doit étendre FragmentStatePagerAdapter

1
répondu nebyan 2017-08-15 07:58:30

j'utilise EventBus bibliothèque pour mettre à jour Fragment contenu dans ViewPager . La logique est simple, tout comme document de EventBus comment faire . Il n'est pas nécessaire de contrôler l'instance FragmentPagerAdapter . Le code est ici:

1: Définir les événements

définit quel message doit être mis à jour.

public class UpdateCountEvent {
    public final int count;

    public UpdateCountEvent(int count) {
        this.count = count;
    }
}

2.Préparer les abonnés

écrire ci-dessous le code dans le Fragment qui doit être mis à jour.

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);  
    super.onStop();
}

public void onEvent(UpdateCountEvent event) {//get update message
    Toast.makeText(getActivity(), event.count, Toast.LENGTH_SHORT).show();
}

3.Post events

écrire le code ci-dessous dans autre Activity ou autre Fragment qui doit mettre à jour le paramètre

//input update message
EventBus.getDefault().post(new UpdateCountEvent(count));
0
répondu Fantasy Fang 2015-02-13 09:38:40

j'avais essayé tellement d'approches différentes, aucune ne sove vraiment mon problème. Voici comment je le résous avec un mélange de solutions fournies par vous tous. Merci à tous.

class PagerAdapter extends FragmentPagerAdapter {

    public boolean flag_refresh=false;

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

    @Override
    public Fragment getItem(int page) {
        FragmentsMain f;
        f=new FragmentsMain();
        f.page=page;
        return f;
    }

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

    @Override
    public int getItemPosition(Object item) {
        int page= ((FragmentsMain)item).page;

        if (page == 0 && flag_refresh) {
            flag_refresh=false;
            return POSITION_NONE;
        } else {
            return super.getItemPosition(item);
        }
    }

    @Override
    public void destroyItem(View container, int position, Object object) {

        ((ViewPager) container).removeView((View) object);
    }
}

Je ne veux rafraîchir la page 0 qu'après onResume().

 adapter=new PagerAdapter(getSupportFragmentManager());
 pager.setAdapter(adapter);

@Override
protected void onResume() {
    super.onResume();

    if (adapter!=null) {
        adapter.flag_refresh=true;
        adapter.notifyDataSetChanged();
    }
}

dans mon FragmentsMain, il y a public integer" page", qui peut me dire si c'est la page que je veux rafraîchir.

public class FragmentsMain extends Fragment {

private Cursor cursor;
private static Context context;
public int page=-1;
0
répondu Ted Hsieh 2015-06-17 01:38:18

je sais que je suis en retard pour la fête. J'ai corrigé le problème en appelant TabLayout#setupWithViewPager(myViewPager); juste après FragmentPagerAdapter#notifyDataSetChanged();

0
répondu theapache64 2015-11-12 03:35:41

Cette solution ne fonctionnera pas pour tout le monde, mais dans mon cas, chaque Fragment dans mon ViewPager est une classe différente, et seulement un d'entre eux existe toujours à la fois.

avec cette contrainte, Cette solution est sûre et doit être utilisée en production.

private void updateFragment(Item item) {

    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    for (Fragment fragment : fragments) {

        if (fragment instanceof MyItemFragment && fragment.isVisible()) {
            ((MyItemFragment) fragment).update(item);
        }

    }
}

si vous avez plusieurs versions du même fragment, vous pouvez utiliser cette même stratégie pour appeler les méthodes sur ces fragments afin de déterminer si c'est le fragment que vous souhaitez mettre à jour.

0
répondu Kevin Grant 2016-07-06 18:00:37

cela pourrait être d'une aide à quelqu'un - dans mon cas, lors de l'insertion d'une nouvelle page le pager de vue demandait la position d'un fragment existant deux fois, mais ne demandant pas la position du nouvel élément, provoquant un comportement incorrect et les données ne s'affichent pas.

  1. copier la source pour FragmentStatePagerAdapter (semble ne pas avoir été mis à jour dans les âges).

  2. Remplacer notifyDataSetChanged()

    @Override
    public void notifyDataSetChanged() {
        mFragments.clear();
        super.notifyDataSetChanged();
    }
    
  3. Ajouter un contrôle de santé mentale à destroyItem () pour prévenir les accidents:

    if (position < mFragments.size()) {
        mFragments.set(position, null);
    }
    
0
répondu Meanman 2016-08-23 13:34:38

j'ai parcouru toutes les réponses ci-dessus et un certain nombre d'autres messages, mais je n'ai toujours pas pu trouver quelque chose qui a fonctionné pour moi (avec différents types de fragments ainsi que l'ajout et la suppression dynamiques des onglets). FWIW suivre l'approche est ce qui a fonctionné pour moi (au cas où quelqu'un d'autre a les mêmes problèmes).

public class MyFragmentStatePageAdapter extends FragmentStatePagerAdapter {
    private static final String TAB1_TITLE = "Tab 1";
    private static final String TAB2_TITLE = "Tab 2";
    private static final String TAB3_TITLE = "Tab 3";

    private ArrayList<String> titles = new ArrayList<>();
    private Map<Fragment, Integer> fragmentPositions = new HashMap<>();


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


    public void update(boolean showTab1, boolean showTab2, boolean showTab3) {
        titles.clear();

        if (showTab1) {
            titles.add(TAB1_TITLE);
        }
        if (showTab2) {
            titles.add(TAB2_TITLE);
        }
        if (showTab3) {
            titles.add(TAB3_TITLE);
        }
        notifyDataSetChanged();
    }


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

    @Override
    public Fragment getItem(int position) {
        Fragment fragment = null;

        String tabName = titles.get(position);
        if (tabName.equals(TAB1_TITLE)) { 
            fragment =  Tab1Fragment.newInstance();
        } else if (tabName.equals(TAB2_TITLE)) {
            fragment =  Tab2Fragment.newInstance();
        } else if (tabName.equals(TAB3_TITLE)) {
            fragment =  Tab3Fragmen.newInstance();
        } 

        ((BaseFragment)fragment).setTitle(tabName);
        fragmentPositions.put(fragment, position);
        return fragment;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return titles.get(position);
    }

    @Override
    public int getItemPosition(Object item) {
        BaseFragment fragment = (BaseFragment)item;
        String title = fragment.getTitle();
        int position = titles.indexOf(title);

        Integer fragmentPosition = fragmentPositions.get(item);
        if (fragmentPosition != null && position == fragmentPosition) {
            return POSITION_UNCHANGED;
        } else {
            return POSITION_NONE;
        }
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        super.destroyItem(container, position, object);
        fragmentPositions.remove(object);
    }
}
0
répondu John O'Reilly 2017-02-05 20:32:07

utiliser FragmentStatePagerAdapter au lieu de FragmentPagerAdapter si vous souhaitez recréer ou recharger des fragments sur la base de l'index Par exemple, si vous voulez recharger un fragment autre que FirstFragment, vous pouvez vérifier l'instance et retourner la position comme ceci

 public int getItemPosition(Object item) {
    if(item instanceof FirstFragment){
       return 0;
    }
    return POSITION_NONE;
 }
0
répondu HemangNirmal 2018-06-11 14:09:09