web-dev-qa-db-fra.com

Afficher le cycle de vie du pager et des fragments

J'ai un ViewPager qui charge trois pages à la fois. Si je glisse de la page 1 à la page 2 puis à la page 3, la première page (fragment) passe à onPause(). Ensuite, si je glisse vers la deuxième page, la 1re page passe à onResume() même si la page 1 n'est toujours pas visible pour l'utilisateur. Ma question est donc la suivante: comment faire la distinction entre la première et la deuxième page du code? Par exemple, si je dois exécuter un morceau de code lorsque le fragment est visible, comment cela se fait-il?

31
shreyas

FragmentPagerAdapter conserve des fragments supplémentaires, en plus de celui indiqué, dans l'état de reprise. La solution consiste à implémenter un module OnPageChangeListener personnalisé et à créer une nouvelle méthode pour l'affichage du fragment.

1) Créer une interface LifecycleManager L’interface aura deux méthodes et chaque fragment de ViewPager l’implémentera. Ces méthodes sont les suivantes:

public interface FragmentLifecycle {

    public void onPauseFragment();
    public void onResumeFragment();

}

2) Laisser chaque fragment implémenter l'interface Ajouter une instruction iplements pour chaque déclaration de classe:

public class FragmentBlue extends Fragment implements FragmentLifecycle
public class FragmentGreen extends Fragment implements FragmentLifecycle
public class FragmentPink extends Fragment implements FragmentLifecycle

3) Implémenter des méthodes d'interface dans chaque fragment Afin de vérifier qu'il fonctionne vraiment comme prévu, je vais simplement enregistrer l'appel de la méthode et montrer à Toast:

@Override
public void onPauseFragment() {
    Log.i(TAG, "onPauseFragment()");
    Toast.makeText(getActivity(), "onPauseFragment():" + TAG, Toast.LENGTH_SHORT).show(); 
}

@Override
public void onResumeFragment() {
    Log.i(TAG, "onResumeFragment()");
    Toast.makeText(getActivity(), "onResumeFragment():" + TAG, Toast.LENGTH_SHORT).show(); 
}

4) Appeler des méthodes d'interface sur le changement de page ViewPager Vous pouvez définir OnPageChangeListener sur ViewPager et obtenir un rappel chaque fois que ViewPager affiche une autre page:

pager.setOnPageChangeListener(pageChangeListener);

5) Implémentez OnPageChangeListener pour appeler vos méthodes Lifecycle personnalisées

Listener connaît la nouvelle position et peut appeler la méthode d'interface sur new Fragment à l'aide de PagerAdapter. Je peux ici appeler onResumeFragment () pour le nouveau fragment et onPauseFragment () pour le fragment actuel.

Je dois également enregistrer la position du fragment actuel (initialement, la position actuelle est égale à 0), car je ne sais pas si l’utilisateur a fait défiler de gauche à droite ou de droite à gauche. Voyez ce que je veux dire dans le code:

private OnPageChangeListener pageChangeListener = new OnPageChangeListener() {

    int currentPosition = 0;

    @Override
    public void onPageSelected(int newPosition) {

        FragmentLifecycle fragmentToShow = (FragmentLifecycle)pageAdapter.getItem(newPosition);
        fragmentToShow.onResumeFragment();

        FragmentLifecycle fragmentToHide = (FragmentLifecycle)pageAdapter.getItem(currentPosition);
        fragmentToHide.onPauseFragment();

        currentPosition = newPosition;
    }

    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) { }

    public void onPageScrollStateChanged(int arg0) { }
};

Je n'ai pas écrit le code. Tutoriel complet ici: http://looksok.wordpress.com/2013/11/02/viewpager-with-detailed-fragment-lifecycle-onresumefragment-including-source-code/

34
Shreyas Shetty

si votre fragment étendre Android.support.v4.app.Fragment

vous pouvez l'utiliser, cela fonctionne pour moi. 

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (!isVisibleToUser) {
        //do sth..
    }
}
7
Hao Qi

Remplacer setUserVisibleHint(). Cette méthode appellera une fois le fragment visible pour l'utilisateur.

2
Parin Parikh

méthode utilisateur pager.setOffscreenPageLimit (nombre) pour définir le nombre de fragments que vous souhaitez conserver dans la pile. 

1
jack

Résoudre votre problème:

public class FragmentVisibleHelper implements LifecycleObserver {

    private static final String TAG = "VipVisibleHelper";

    public interface IVisibleListener {

        void onVisible();

        void onInVisible();
    }

    boolean mIsVisibleToUser;
    boolean mStarted = false;

    volatile boolean mIsCalledVisible = false;
    volatile boolean mIsCalledInvisible = false;


    IVisibleListener mListener;

    public void setListener(IVisibleListener mListener) {
        this.mListener = mListener;
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    void onResume() {
        Log.d(TAG, String.format("%-60s %s", this.toString(), "onResume() called:"));
        if (mIsVisibleToUser) {
            dispatchVisible();
        }
    }

    private void dispatchVisible() {
        Log.d(TAG, String.format("%-60s %s", this.toString(), "dispatchVisible() called mIsCalledVisible = [" + mIsCalledVisible + "] mIsCalledInvisible = [" + mIsCalledInvisible + "] "));
        if (!mIsCalledVisible) {
            mIsCalledVisible = true;
            mIsCalledInvisible = false;

            if (Profile.LOG) {
                Log.d(TAG, String.format("%-60s %s", this.toString(), "dispatchVisible() called onVisible"));
            }

            if (mListener != null) {
                mListener.onVisible();
            }
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    void onPause() {
        Log.d(TAG, String.format("%-60s %s", this.toString(), "onPause() called:"));
        if (mIsVisibleToUser) {
            dispatchInvisible();
        }
    }

    private void dispatchInvisible() {
        Log.d(TAG, String.format("%-60s %s", this.toString(), "dispatchInvisible() called mIsCalledVisible = [" + mIsCalledVisible + "] mIsCalledInvisible = [" + mIsCalledInvisible + "] "));
        if (!mIsCalledInvisible) {
            mIsCalledInvisible = true;
            mIsCalledVisible = false;

            if (Profile.LOG) {
                Log.d(TAG, String.format("%-60s %s", this.toString(), "dispatchInvisible() called onInVisible"));
            }

            if (mListener != null) {
                mListener.onInVisible();
            }
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    void onStart() {
        Log.d(TAG, String.format("%-60s %s", this.toString(), "onStart() called"));
        mStarted = true;
        if (mIsVisibleToUser) {
            dispatchVisible();
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    void onStop() {
        Log.d(TAG, String.format("%-60s %s", this.toString(), "onStop() called"));
        if (mIsVisibleToUser) {
            dispatchInvisible();
        }
        mStarted = false;
    }

    public void setUserVisibleHint(boolean isVisibleToUser) {
        Log.d(TAG, String.format("%-60s %s", this.toString(), "setUserVisibleHint() called with: isVisibleToUser = [" + isVisibleToUser + "]:"));
        mIsVisibleToUser = isVisibleToUser;
        if (mStarted) { // fragment have created
            if (mIsVisibleToUser) {
                dispatchVisible();
            } else {
                dispatchInvisible();
            }
        }
    }

    public boolean isVisibleToUser() {
        return mIsVisibleToUser;
    }
}
0
biezhihua

Remplacer setUserVisibleHint () cela appellera quand fragment sera visible pour l'utilisateur

0
venu46