web-dev-qa-db-fra.com

onPageSelected ne fonctionne pas pour la première page

Mon adaptateur de pageur (étend PagerAdepter) contient une vue de texte. Et je mets à jour cette textview avec onPageSelected de MainActivity. Sa mise à jour du texte pour position> 0, mais la page de démarrage (position 0) ne se met pas à jour au démarrage. Lorsque je glisse vers l'avant, puis vers l'arrière; il définit la valeur pour la position 0 MAIS je ne pouvais pas définir la valeur ON START. Comment définir une valeur pour la page étoile?

public void onPageSelected(int position) {

             switch (position) {
                case 0: 

                     PagerAdapter.tv.setText("value"); // => doesnt work on start

                    break;

                            default:
                                   PagerAdapter.tv.setText("value");
                                         break;
}
}

Code complet:

public class QuizStart extends SlidingFragmentActivity {
 @Override
        protected void onCreate(final Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

           this.setContentView(R.layout.activity_main);

              mPager = (ViewPager)findViewById(R.id.pager);         
            QuestionPagerAdapter mAdapter = new QuestionPagerAdapter();

            mPager.setAdapter(mAdapter);
            QuizStart.onPageSelected(0);

         mPager.setOnPageChangeListener(new OnPageChangeListener() {


            @Override
            public void onPageScrollStateChanged(int arg0) { }

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

            @Override
            public void onPageSelected(int position) {

             switch (position) {
                case 0: 

                     PagerAdapter.tv.setText("value"); // => doesnt work on start

                    break;

                            default:
                                   PagerAdapter.tv.setText("value");
                                         break;
                }
            }

        });
}
}
49
metemet06

Vous pouvez appeler manuellement onPageSelected(0) lorsque vous créez votre OnPageChangeListener pour définir l’état de départ:

OnPageChangeListener pageChangeListener = new OnPageChangeListener() {
    @Override
    public void onPageScrollStateChanged(int arg0) { }

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

    @Override
    public void onPageSelected(int position) {

        switch (position) {
        case 0: 
            QuizStart.next.setText(getmycurrentpage()+"");
            break;

        default:

            QuizStart.next.setText(getmycurrentpage()+"");
            break;
        }
    }
});

   mPager.setOnPageChangeListener(pageChangeListener);
   // do this in a runnable to make sure the viewPager's views are already instantiated before triggering the onPageSelected call
   mPager.post(new Runnable()
   {
       @Override
       public void run() 
       {
           pageChangeListener .onPageSelected(viewPager.getCurrentItem());
       }
   });

Modifier  

Maintenant, il n'aura pas Null Pointer exception comme indiqué par @ metemet06

60
ianhanniballake

Pour moi, travailler le code suivant

    viewPager.addOnPageChangeListener(myOnPageChangeListener);

.

    ViewPager.OnPageChangeListener myOnPageChangeListener = new ViewPager.OnPageChangeListener() {

    //declare key
    Boolean first = true;

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        if (first && positionOffset == 0 && positionOffsetPixels == 0){
            onPageSelected(0);
            first = false;
        }
    }

    @Override
    public void onPageSelected(int position) {
        //do what need
    }

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

Ma solution consistait à étendre l'adaptateur de pageur et à créer une interface à l'intérieur. Ensuite, assurez-vous que l’adaptateur n’appelle l’interface qu’une seule fois après sa création. Dans l'interface de rappel, vous pouvez appeler la méthode onPageChanged sans avoir nullpointerexception. Ajoutez cette classe à votre projet et développez votre adaptateur à partir de celui-ci. N'oubliez pas de configurer l'auditeur sur l'adaptateur avant de configurer l'adaptateur sur ViewPager. Classe d'adaptateur ci-dessous:

public abstract class ExtendedPagerAdapter extends FragmentPagerAdapter {

private boolean instantiated;
private AdapterListener adapterListener;

public interface AdapterListener {
    void onAdapterInstantiated();
}

public ExtendedPagerAdapter(FragmentManager fragmentManager) {
    this(fragmentManager, null);
}

public ExtendedPagerAdapter(FragmentManager fragmentManager, AdapterListener adapterListener) {
    super(fragmentManager);
    this.adapterListener = adapterListener;
    instantiated = false;
}

@Override
public void finishUpdate(ViewGroup container) {
    super.finishUpdate(container);
    if (!instantiated) {
        instantiated = true;
        if (adapterListener != null) {
            adapterListener.onAdapterInstantiated();
        }
    }
}

public void setAdapterInstantiatedListener(AdapterListener adapterListener) {
    this.adapterListener = adapterListener;
}
}
4
Arūnas Bedžinskas

J'ai corrigé le problème dans mon application en ajoutant le code à exécuter pour la première page de la méthode onCreate () de mon activité. 

Ce n'est pas le plus beau bidouillage et implique du code redondant, mais comme je veux seulement charger des données de texte lorsque les pages changent, c'est la façon la plus simple de le faire dans mon cas. 

L'appel à onPageSelected () a provoqué manuellement NullPointerExceptions, comme décrit dans les commentaires précédents.

1
Luigi_Papardelle

Ce code fonctionne pour moi. Commencez par initialiser l'écouteur de changement de page. Après setCurrentItem. 

viewPager.setAdapter(adapter);
      viewPager.setOffscreenPageLimit(1);

      final ViewPager.OnPageChangeListener listener = new ViewPager.OnPageChangeListener() {
         @Override
         public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
         }

         @Override
         public void onPageSelected(int position) {

         }

         @Override
         public void onPageScrollStateChanged(int state) {
         }
      };
      viewPager.addOnPageChangeListener(listener);
      viewPager.setCurrentItem(position);
0
mustafasevgi

Ma solution est une extension ViewPager

class MyViewPager extends ViewPager {

    private List<OnPageChangeListener> _Listeners = new ArrayList<>();

    public MyViewPager(Context context) {
        super(context);
    }

    public MyViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void addOnPageChangeListener(OnPageChangeListener listener) {
        super.addOnPageChangeListener(listener);
        _Listeners.add(listener);
    }

    @Override
    public void removeOnPageChangeListener(OnPageChangeListener listener) {
        super.removeOnPageChangeListener(listener);
        _Listeners.remove(listener);
    }

    @Override
    public void setCurrentItem(final int item) {
        if (item != getCurrentItem()) {
            super.setCurrentItem(item);
        } else {
            post(new Runnable() {
                @Override
                public void run() {
                    dispatchOnPageSelected(item);
                }
            });
        }
    }

    private void dispatchOnPageSelected(int position) {
        for (int i = 0, size = _Listeners.size(); i < size; i++) {
            OnPageChangeListener listener = _Listeners.get(i);
            if (listener != null) {
                listener.onPageSelected(position);
            }
        }
    }
}
0
steven274

Il me semble que ce que vous voulez vraiment faire est de remplacer getPageTitle() , puis, quelque part, de saisir le titre de la page et de le définir comme un texte TextView.

Ainsi, lorsque vous initialisez votre activité, initialisez le PagerAdapter et appelez getTitle(0). Cela vous donnera le titre de la page 0. Maintenant, définissez-le dans la vue texte de l'activité. Plus tard, chaque fois que vous changez de page, appelez simplement getTitle(newPosition) et mettez à jour ce TextView.

0
dmon
@Override
public void addOnPageChangeListener(@NonNull OnPageChangeListener listener) {
    super.addOnPageChangeListener(listener);
    if (getAdapter() != null && getAdapter().getCount() > 0) {
        post(() -> listener.onPageSelected(getCurrentItem()));
    }
}
0
erlei liu

Parce que j'ai fait ce qui a été suggéré ici et que cela n'a pas fonctionné, je vais publier ce qui a fonctionné pour moi, c'est ajouter la fonction d'instanciation à onPageScrolled, comme suit:

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

           adapter.closeText(arg0, viewPager);

    }

La raison pour laquelle cela a fonctionné est probablement que onPagesScrolled est activé plus loin dans la ligne du gestionnaire de tâches Android, nous évitons donc la situation indésirable où la page est gonflée en ignorant l'attachement des écouteurs à la vue.

0
sivi

En fait, j’ai trouvé un bon moyen de partir de cette réponse .

Le problème est que la ViewPager n'est pas complètement chargée lorsque l'écouteur est configuré, la première page est appelée mais les fragments à l'intérieur de la ViewPager ne sont pas encore complètement initialisés.

Afin de remédier à cela, je garde une variable pour savoir si la première page a été appelée ou non:

private boolean mFirstPageCalled = false;

Puis dans l'auditeur:

@Override
public void onPageSelected(int position) {

    if(mFirstPageCalled) {
        // Do your thing
    } else {
        mFirstPageCalled = true;
    }
}

La dernière chose à faire est de gérer la première page manquante. Cela peut être fait une fois que la variable ViewPager a été entièrement créée avec:

    mViewPager.post(new Runnable(){
        @Override
        public void run() {
            // Do your thing
        }
    });

Dans mon cas, je rappelle ici le fragment actuel montré et travaille dessus:

Fragment currentFragment = mPagerAdapter.instantiateItem(mViewPager, mViewPager.getCurrentItem());
currentFragment.customAction();

La méthode post n'est appelée qu'une fois, ce qui est parfait pour gérer le cas de la première page.

0
Yoann Hercouet

Vous utilisez probablement des tâches asynchrones pour charger le jeu de données et il est difficile de déterminer quelle tâche sera la dernière à se terminer. Et seulement après cette dernière tâche, lorsque l'ensemble du jeu de données est terminé, vous pouvez appeler OnPageSelected, car il purge l'interface utilisateur sur l'ensemble du jeu de données.

Au lieu d'appeler manuellement la fonction OnPageSelected lorsque la page est chargée pour la première fois, créez plutôt l'interface utilisateur pas à pas la voie "normale". Plus tard, lorsque l'utilisateur change de page, l'ensemble de données doit être complet et il est sauvegardé pour laisser la mise à jour effectuée dans la fonction OnPageSelected.

0