web-dev-qa-db-fra.com

ViewPager avec des fragments - onPause (), onResume ()?

Lors de l'utilisation de ViewPager avec des fragments, nos méthodes onPause (), onResume () ne sont pas appelées lors du déplacement entre les onglets. Y a-t-il un moyen de comprendre dans le fragment que nous sommes rendus visibles ou cachés? 

Malheureusement, j’ai une logique dans onResume (), onPause (), comme pour l’enregistrement auprès des services de localisation, qui ne s’arrête jamais lors du changement d’onglet, car onPause () n’est jamais appelé tant que l’application n’a pas été complètement fermée.

Merci

43
user291701

ViewPager est livré avec l’interface OnPageChangeListener . En définissant des indicateurs pour les pages précédentes et actuellement affichées, vous pouvez émuler ce comportement.

17
Phix

Considérant que les solutions précédentes ne sont pas très claires, voici comment je l’ai résolue grâce à Phix pour son indice:

Dans le rappel OnPageChange ():

    Fragment old_fragment = getActiveFragment(old_position);
    Fragment new_fragment = getActiveFragment(new_position);
    old_f.setUserVisibleHint(false);
    old_f.onPause();
    new_f.setUserVisibleHint(true);
    new_f.onResume();

Puis dans onResume ():

    if (getUserVisibleHint())
        /* resume code */

et dans onPause ():

    if (!getUserVisibleHint())
        /* pause code */

Voici le code getActiveFragment, en évitant de rechercher cela aussi:

    return fragmentManager.findFragmentByTag("Android:switcher:" + viewPagerId + ":" + position);

NB: Fragment a une méthode isVisible (), mais elle ne semble pas très cohérente, d’où l’utilisation de UserVisibleHint.

EDIT: remplace UserVisibleHint par un indicateur privé. Travaillé beaucoup mieux!

10
3c71

Si vous utilisez Android Support Library (rév 11), vous pouvez utiliser getUserVisibleHint () ou override setUserVisibleHint () pour capturer les modifications visibles et les masquer. Look This post .

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        // do something when visible.
    }
}

3
Evan

Solution 1:

Définissez une SparseArray dans vos adaptateurs ViewPagers 'comme ci-dessous. Dans ce tableau, nous allons tenir l'instance de fragments.

SparseArray<Fragment> registeredFragments = new SparseArray<>();

Et Override la méthode instantiateItem de votre adaptateur.

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Fragment fragment = (Fragment) super.instantiateItem(container, position);
    registeredFragments.put(position, fragment);
    return fragment;
}

Aussi OverridedestroyItem méthode de votre ViewPagers

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    registeredFragments.remove(position);
    super.destroyItem(container, position, object);
}

Et définissez une nouvelle méthode pour obtenir votre instance ViewPagerFragments.

public Fragment getRegisteredFragment(int position) {
    return registeredFragments.get(position);
} 

Maintenant, vous pouvez implémenter votre logique avec ViewPager'sOnPageChangeListener. Voici un exemple de la manière dont vous pouvez implémenter la onPageChangeListener d'un viewpager:

Définissez un entier pour conserver la position actuelle:

int currentPos;

yourViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                // Empty method
            }

            @Override
            public void onPageSelected(int position) {
                  // This is paused fragment.
                  final Fragment pausedFragment = yourAdapter.getRegisteredFragment(currentPos);

                  // update current position value
                  currentPos = position;

                  // This is resumed fragment
                  final Fragment resumedFragment = yourAdapter.getRegisteredFragment(currentPos);
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                // Empty method
            }
        });

Enfin, pour restaurer l’état de l’instance, mettez à jour votre position actuelle afin de maintenir à jour la position dans laquelle l'utilisateur a laissé ViewPager

currentPos = yourViewPager.getCurrentItem();

Solution 2:

Pour une autre solution, vous pouvez trouver votre ViewPagerFragments par Tag. Vous pouvez générer votre tag avec:

@NonNull
public static String generateViewPagerFragmentTag(int viewPagerId, int position) {
        final StringBuilder tagBuilder = new StringBuilder();
        tagBuilder.append("Android:switcher:");
        tagBuilder.append(viewPagerId);
        tagBuilder.append(":");
        tagBuilder.append(position);
        return tagBuilder.toString();
    }

Et trouvez votre Fragment:

final Fragment yourFragment = getSupportFragmentManager().findFragmentByTag(generateViewPagerFragmentTag(R.id.your_viewpager, currentPos));

Edit: Il y a quelques années, alors que je cherchais une solution pour obtenir l'élément actuel de ViewPager, j'ai essayé UserVisibleHint dans Fragments et j'ai remarqué qu'il n'était pas fiable. Je ne sais pas si c'est fiable ou pas maintenant, mais j'évite quand même de l'utiliser. 

3
savepopulation

Vous pouvez utiliser la méthode ci-dessous dans Fragment

public void setUserVisibleHint(boolean isVisibleToUser){

}

lorsque isVisibleToUser == true, le fragment est affiché

2
tainy

Pour donner un peu plus de définition aux méthodes de la réponse de savepopulation :

yourPager.setOnPageChangeListener(new GridViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int row, int column, float rowOffset, float columnOffset, int rowOffsetPixels, int columnOffsetPixels) {

        }

        @Override
        public void onPageSelected(int row, int column) {
            // When on page selected if position is not specific for you
            // you can find your fragment or you can switch position.
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });
0
suomi35

Un peu tard pour la fête, mais dans mon application actuelle, j'ai défini OffScreenPageLimit sur 1 pour mon viewpager, cela signifie que les fragments ne sont pas mis en cache et que chaque fois que la vue change, elle recharge le fragment actuel

https://developer.Android.com/reference/Android/support/v4/view/ViewPager.html#getOffscreenPageLimit ()

0
Phil