web-dev-qa-db-fra.com

ViewPager.setOffscreenPageLimit (0) ne fonctionne pas comme prévu

Les fragments que j'utilise dans mon instance ViewPager nécessitent beaucoup de ressources. Je ne voudrais donc en charger qu'un à la fois. Quand j'essaye ce qui suit:

mViewPager.setOffscreenPageLimit(0);
mViewPager.setAdapter(mPagerAdapter);

Ma fonction de substitution FragmentStatePagerAdapter.getItem(int position) est appelée 3 fois, ce qui se produit lorsque j'appelle mViewPager.setOffscreenPageLimit(1). Je m'attendrais à ce qu'il ne soit appelé qu'une seule fois, car j'ai spécifié 0 pages hors écran. 

Je crois que j'appelle tout correctement, car si j'appelle mViewPager.setOffscreenPageLimit(2), FragmentStatePagerAdapter.getItem(int position) est appelé 5 fois, comme je l'aurais cru. 

ViewPager nécessite-t-il un minimum de 1 pages hors écran, ou est-ce que je fais quelque chose de mal ici? 

91
Chris Lacy

ViewPager nécessite-t-il un minimum de 1 pages hors écran?

Oui. Si je lis correctement le code source, vous devriez recevoir un avertissement à ce sujet dans LogCat, par exemple:

Requested offscreen page limit 0 too small; defaulting to 1
108
CommonsWare

Le meilleur moyen que j'ai trouvé était setUserVisibleHint
Ajoutez ceci à votre fragment 

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        // load data here
    }else{
       // fragment is no longer visible
    }
}
113
Tyler Davis

Premier ajout 

   boolean isFragmentLoaded = false;

que

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser && !isFragmentLoaded) {
        //Load Your Data Here like.... new GetContacts().execute();

        isFragmentLoaded = true;
    }
else{
     }
}
7
user5308871

Vous pouvez essayer comme ça:

public abstract class LazyFragment extends Fragment {
    protected boolean isVisible;
    /**
     * 在这里实现Fragment数据的缓加载.
     * @param isVisibleToUser
     */
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if(getUserVisibleHint()) {
            isVisible = true;
            onVisible();
        } else {
            isVisible = false;
            onInvisible();
        }
    }
    protected void onVisible(){
        lazyLoad();
    }
    protected abstract void lazyLoad();
    protected void onInvisible(){}

protected abstract void lazyLoad();
protected void onInvisible(){}
6
Terry

dans mon cas, je voulais commencer quelques animations dans les vues, mais avec setUserVisibleHint j'ai eu quelques problèmes ...
ma solution est:

1/addOnPageChangeListener pour votre adaptateur:

mViewPager.addOnPageChangeListener(this);

2/implémenter OnPageChangeListener:

public class PagesFragment extends Fragment implements ViewPager.OnPageChangeListener

3/outrepasser les 3 méthodes:

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{

}

@Override
public void onPageSelected(int position)
{ 
}

@Override
public void onPageScrollStateChanged(int state)
{
}

4/déclarer et initialiser cette variable sur votre classe

private static int mTabState = 1;

notice : j’ai trois fragments dans mon adaptateur et utilise mTabState pour setCurrentItem et la position actuelle de l’adaptateur qui reconnaît le fragment affiché à l’utilisateur dans le temps ... 5/dans la méthode onPageSelected, ajoutez les codes suivants:

if (mTabState == 0 || position == 0)
    {
        Intent intent = new Intent("animation");
        intent.putExtra("current_position", position);
        LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
    }

si la page précédente ou la page en cours est la page 0 (fragment en position 0) alors fais ce genre de choses 

6/maintenant dans votre classe de fragment (fragment en position 0 de l'adaptateur), vous devez créer un récepteur de radiodiffusion et l'enregistrer dans la méthode onResume et l'annuler de l'enregistrement onPause methos:

BroadcastReceiver broadcastReceiver = new BroadcastReceiver()
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        if (Objects.equals(intent.getAction(), "animation"))
        {
            int currentPosition = intent.getIntExtra("current_position", 0);
            if (currentPosition == 0)
            {
                startAnimation();
                setViewsVisible();
            } else
            {
                setViewsInvisible();
            }
        }
    }
};

@Override
public void onResume()
{
    super.onResume();
    LocalBroadcastManager.getInstance(mContext).registerReceiver(broadcastReceiver, new IntentFilter("animation"));
}

@Override
public void onPause()
{
    super.onPause();
    LocalBroadcastManager.getInstance(mContext).unregisterReceiver(broadcastReceiver);
}

résumé: j’ai un adaptateur Fragment Pager qui montre trois fragments, je souhaite afficher quelques animations sur les vues de fragment en position 0 de l’adaptateur, pour cela j’utilise BroadcastReceiver. Lorsque le fragment est sélectionné, je lance la méthode d'animation et affiche les vues à l'utilisateur. Lorsque le fragment ne s'affiche pas à l'utilisateur, j'essaie d'utiliser des vues invisibles ...

1
AREF

ViewPager charge par défaut la page suivante (fragment) que vous ne pouvez pas modifier avec setOffscreenPageLimit (0). Mais vous pouvez faire quelque chose à pirater. Vous pouvez implémenter la fonction onPageSelected dans Activity contenant le ViewPager. Dans le prochain fragment (que vous ne voulez pas charger), vous écrivez une fonction, disons showViewContent (), dans laquelle vous insérez tout le code init consommant des ressources et ne faisant rien avant la méthode onResume (). Ensuite, appelez la fonction showViewContent () dans onPageSelected. J'espère que cela aidera.

1

c'est peut-être un vieux fil mais cela semble fonctionner pour moi. Remplacer cette fonction:

@Override
public void setMenuVisibility(boolean menuVisible) { 
    super.setMenuVisibility(menuVisible);

    if ( menuVisible ) {
        /**
         * Load your stuffs here.
         */
    } else  { 
        /**
         * Fragment not currently Visible.
         */
    } 
}

codages heureux ...

0
ralphgabb

J'ai un peu le même problème. J'ai trouvé du code utile sur ce site et le transforme.

Le min int pour mViewPager.setOffscreenPageLimit (...); est égal à 1, donc même si vous le changez en 0, vous aurez toujours 2 pages chargées.

La première chose à faire est de créer un int statique, nous allons appeler maxPageCount et remplacer la méthode FragmentStatePagerAdapter getCount () pour renvoyer maxPageCount:

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

Créez ensuite une méthode statique accessible de n’importe où dans le programme qui vous permettra de changer ce maxCount:

public static void addPage(){
    maxPageCount++; //or maxPageCount = fragmentPosition+2
    mFragmentStatePagerAdapter.notifyDataSetChanged(); //notifyDataSetChanged is important here.
}

Initialisez maintenant maxPageCount sur 1. Vous pouvez ajouter une autre page à tout moment. Dans mon cas, lorsque j’avais besoin que l’utilisateur traite la page en cours avant de générer l’autre. Il le fait et puis, sans problème, peut glisser à la page suivante. 

J'espère que ça aidera quelqu'un.

0
K20

Utilisez ceci // crée un booléen pour récupérer des données booléen privé isViewShown = false;

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (getView() != null) {
        isViewShown = true;
        // fetchdata() contains logic to show data when page is selected mostly asynctask to fill the data
        fetchData();
    } else {
        isViewShown = false;
    }
} 
0
Rohit Sharma

pour la fonction "instantiateItem", préparez simplement le fragment, mais ne chargez pas le contenu lourd.

Utilisez "onPageChangeListener" pour que chaque fois que vous accédez à une page spécifique, vous chargez son contenu lourd et l'affichez.

0
android developer

Veuillez essayer ce code pour résoudre le problème de rafraîchissement de la vue dans Viewpager ....

/* DO NOT FORGET! The ViewPager requires at least “1” minimum OffscreenPageLimit */
int limit = (mAdapter.getCount() > 1 ? mAdapter.getCount() - 1 : 1);
mViewPager.setOffscreenPageLimit(limit);
0
Abhijeet Sharma