web-dev-qa-db-fra.com

Mettre à jour un fragment de ViewPager

J'ai un Activity avec un ViewPager. J'ai aussi une Dialog qui va récupérer une liste avec quelques éléments que l'utilisateur choisira. Maintenant, comment puis-je mettre à jour la Fragment où les éléments sont censés afficher de nouvelles vues attachées à ce fragment? 

Voici l'adaptateur de ma ViewPager:

public static class MyAdapter extends FragmentPagerAdapter {
    public MyAdapter(FragmentManager fm) {
        super(fm);
    }

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

    @Override
    public Android.support.v4.app.Fragment getItem(int position) {
        switch (position) {
        case 0:
            return new Fragment1();

        default:
            return null;
        }
    }
}

Maintenant, voici la Fragment:

public class Fragment1 extends Fragment{

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onActivityCreated(savedInstanceState);
}

@Override
public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
}

@Override
public ViewGroup onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    ViewGroup view = (ViewGroup)inflater.inflate(R.layout.screen1, container, false);
    }
    return view;
}

}

C’est la méthode que je veux utiliser pour ajouter des éléments à ma Fragment

private void addItem() {

    // Instantiate a new "row" view.

    final ViewGroup[] newViews = new ViewGroup[selectedItems.length];


    for(int i = 0; i < selectedItems.length; i++){
        newViews[i] = (ViewGroup) LayoutInflater.from(this).inflate(
                    R.layout.animated_layout_item, mContainerView, false);

        // Set the text in each new row.
        ((TextView) newViews[i].findViewById(Android.R.id.text1)).setText(selectedItems[i]);

        // Because mContainerView has Android:animateLayoutChanges set to true,
        // adding this view is automatically animated.

            mContainerView.addView(newViews[i], 0);


        // Set a click listener for the "X" button in the row that will remove the row.
        OnClickListener listener = new MyAddItemListener(newViews[i], mContainerView, this);
        newViews[i].findViewById(R.id.delete_button).setOnClickListener(listener);

    }


}
46
Luis Lavieri

Mettre à jour un fragment de ViewPager

Vous devez implémenter la méthode getItemPosition(Object obj).

Cette méthode est appelée quand vous appelez

notifyDataSetChanged()

sur votre ViewPagerAdaper. Implicitement, cette méthode renvoie POSITION_UNCHANGED valeur qui signifie quelque chose comme ceci: "Le fragment est là où il devrait être, alors ne changez rien."

Donc si vous avez besoin de mettre à jour Fragment vous pouvez le faire avec:

  • Toujours renvoyer POSITION_NONE de la méthode getItemPosition(). Cela qui Signifie: "Le fragment doit toujours être recréé"
  • Vous pouvez créer une méthode update () qui mettra à jour votre fragment Fragment (fragment gérera les mises à jour elles-mêmes).

Exemple de seconde approche:

public interface Updateable {
   public void update();
}


public class MyFragment extends Fragment implements Updateable {

   ...

   public void update() {
     // do your stuff
   }
}

Et dans FragmentPagerAdapter, vous ferez quelque chose comme ceci:

@Override
public int getItemPosition(Object object) {
   MyFragment f = (MyFragment ) object;
   if (f != null) {
      f.update();
   }
  return super.getItemPosition(object);
}

Et si vous choisissez d'abord l'approche, elle peut ressembler à:

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

Note: / Cela vaut la peine de réfléchir à l'approche que vous allez adopter.

109
Simon Dorociak

J'ai parfois rencontré des problèmes pour que dans ce cas, toujours évitez FragmentPagerAdapter et utilisez FragmentStatePagerAdapter. 

Ça marche pour moi. J'espère que cela fonctionnera pour vous aussi.

26
Yogendra

J'implémente une démo d'application à la suite de la réponse de Sajmon ... uniquement aux personnes cherchant cette question.

Vous pouvez accéder au code source sur GitHub

 enter image description here

13
li2

Dans votre PagerAdapter, substituez getItemPosition

@Override
public int getItemPosition(Object object) {
// POSITION_NONE makes it possible to reload the PagerAdapter
return POSITION_NONE;
}

Après cela, ajoutez viewPager.getAdapter (). NotifyDataSetChanged (); ce code comme ci-dessous

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            viewPager.getAdapter().notifyDataSetChanged();
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });

devrait marcher.

10
madhu sudhan

Vous pouvez mettre à jour le fragment de deux manières différentes,

Première voie

comme @Sajmon

Vous devez implémenter la méthode getItemPosition(Object obj).

Cette méthode est appelée quand vous appelez

notifyDataSetChanged()

Vous pouvez trouver un exemple dans Github et plus d’informations dans ce post .

 enter image description here

Deuxième voie

Mon approche pour mettre à jour des fragments dans le viewpager consiste à utiliser la méthode setTag() pour toute vue instanciée dans la méthode instantiateItem(). Ainsi, lorsque vous souhaitez modifier les données ou invalider la vue dont vous avez besoin, vous pouvez appeler la méthode findViewWithTag() sur ViewPager pour récupérer la vue précédemment instanciée et la modifier/utiliser à votre guise sans avoir à supprimer/créer une nouvelle vue à chaque fois. vous voulez mettre à jour une valeur.

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Object object = super.instantiateItem(container, position);
    if (object instanceof Fragment) {
        Fragment fragment = (Fragment) object;
        String tag = fragment.getTag();
        mFragmentTags.put(position, tag);
    }
    return object;
}

public Fragment getFragment(int position) {
    Fragment fragment = null;
    String tag = mFragmentTags.get(position);
    if (tag != null) {
        fragment = mFragmentManager.findFragmentByTag(tag);
    }
    return fragment;
}

Vous pouvez trouver un exemple dans Github ou plus d’informations dans ce post :

 enter image description here

4
Cabezas

Très simple pour remplacer la méthode dans le fragment:

@Override

public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);

    if(isVisibleToUser){
        actionView();
    }
    else{
        //no
    }      
}
3
Issac Balaji

Si vous utilisez Kotlin, vous pouvez effectuer les opérations suivantes:

1. Le premier , vous devriez être créer Interface et le mettre en œuvre dans votre Fragment

interface RefreshData {
    fun refresh()
}

class YourFragment : Fragment(), RefreshData {
    ...
    override fun refresh() {
        //do what you want
    }
}

2. Étape suivante est d'ajouter OnPageChangeListener à votre ViewPager

viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
    override fun onPageScrollStateChanged(state: Int) { }

    override fun onPageSelected(position: Int) {
        viewPagerAdapter.notifyDataSetChanged()
        viewPager.currentItem = position
    }

    override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { }
})

3. remplacer getItemPosition dans votre Adapter

override fun getItemPosition(obj: Any): Int {
    if (obj is RefreshData) {
        obj.refresh()
    }
    return super.getItemPosition(obj)
}
2
Danil

Une solution très simple mais efficace pour mettre à jour vos vues de fragments . Utilisez la méthode setUserVisibleHint(). Il sera appelé lorsque le fragment sera sur le point d'être visible pour l'utilisateur. Là vous pouvez mettre à jour notre vue (setText() ou setVisibility() etc.) 

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);

    if(isVisibleToUser){
       //Write your code to be executed when it is visible to user
    }
}

Cela a fonctionné dans mon cas. J'espère que ça aide! 

2
Tahmid Rahman

Réponse acceptée n'est pas comprendre, Voilà pourquoi ajouté solution facile. après une longue lutte trouver une solution de travail.

Juste notifiez votre adaptateur , ça marche à merveille,

Code de référence

 void setAdapter(int position) {
        PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager());
        viewPager.setAdapter(pagerAdapter);
        // when notify then set manually current position.
        viewPager.setCurrentItem(position);
        pagerAdapter.notifyDataSetChanged();
    }

appelez ce code lorsque vous définissez l'adaptateur et lorsque vous souhaitez actualiser l'interface utilisateur.

Dans votre fragment, ajoutez ce code pour l'actualisation

((YourActivityName) getContext()).setAdapter(selectedTabPosition);

Utilisez instanceof pour le contexte de la distribution.

Ce code partage uniquement le but utile qui trouve une solution.

2
Yogesh Rathi

Peut-être que votre méthode pour ajouter des éléments dans un fragment devrait être public (placé dans le fragment souhaité) et devrait avoir le même type de paramètre que selectedItems. 

Cela le rendra visible depuis l'activité, qui aura selectedItems array et voila .. 

p.s. mieux le nommer addItemsFromArray(typeOfSelectedItems[] pSelectedItems) cause cause nom addItem() est tout à fait descriptif 

Edit: stackoverflow vient de suggérer un sujet similaire :) Vérifiez ici pour une implémentation détaillée de l’idée .. :)

1
Ewoks

j'avais 4 fragments dans le ViewPager, mais je voulais mettre à jour un fragment "FavoriteFragment" à la position 0 du viewPager, à chaque fois que l'utilisateur cliquait sur ce fragment . un fragment que je veux. J'ai donc essayé et cela fonctionne pour moi:

dans mon FavoriteFragment j'ai surchargé onResume ()

@Override
    public void onResume() {
        super.onResume();
        updateUI(); // code to update the UI in the fragment
    }

dans l'activité hébergeant le viewPager, remplacez addOnPageChangeListener() et ajoutez ce code

mViewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);

                if(position == 0) { // 0 = the first fragment in the ViewPager, in this case, the fragment i want to refresh its UI
                    FavoritesFragment fragment = (FavoritesFragment) mViewPager.getAdapter().instantiateItem(mViewPager, position); 
                    fragment.onResume(); // here i call the onResume of the fragment, where i have the method updateUI() to update its UI
                    mViewPager.getAdapter().notifyDataSetChanged();
                }
            }
        });

et cela fonctionne parfaitement pour moi, pour actualiser/recharger juste le fragment que je veux.

0
korchix

1) Créez un gestionnaire dans le fragment que vous souhaitez mettre à jour.

public static Handler sUpdateHandler;

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ...

        sUpdateHandler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                // call you update method here.
            }
        };
    }

2) Dans l'activité/le fragment/la boîte de dialogue, si vous souhaitez que l'appel de mise à jour soit déclenché, obtenez la référence à ce gestionnaire et envoyez un message (indiquant à votre fragment de se mettre à jour)

// Check if the fragment is visible by checking if the handler is null or not.
Handler handler = TaskTabCompletedFragment.sUpdateHandler;
if (handler != null) {
    handler.obtainMessage().sendToTarget();
}
0
Astonvish32