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
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.
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!
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.
}
}
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 Override
destroyItem
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 ViewPager
Fragments
.
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
Maintenant, vous pouvez implémenter votre logique avec ViewPager's
OnPageChangeListener
. 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 ViewPager
Fragments
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.
Vous pouvez utiliser la méthode ci-dessous dans Fragment
public void setUserVisibleHint(boolean isVisibleToUser){
}
lorsque isVisibleToUser == true
, le fragment est affiché
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) {
}
});
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