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;
}
}
});
}
}
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
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;
}
}
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.
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);
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);
}
}
}
}
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.
@Override
public void addOnPageChangeListener(@NonNull OnPageChangeListener listener) {
super.addOnPageChangeListener(listener);
if (getAdapter() != null && getAdapter().getCount() > 0) {
post(() -> listener.onPageSelected(getCurrentItem()));
}
}
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.
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.
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.