90 votes

ViewPager ne redessine pas le contenu, reste / devient vide

Nous souffrons d'un très étrange problème avec ViewPager ici. Nous avons intégré les listes de chaque ViewPager page, et de déclencher notifyDataSetChanged à la fois sur la liste de l'adaptateur et de la vue pager de l'adaptateur lorsque la mise à jour de la liste de données.

Ce que nous observons, c'est que parfois, la page n'est pas mise à jour de son point de vue, arbre, c'est à dire rien, ou parfois même disparaît lors de la pagination. Lors de la pagination en avant et en arrière à quelques reprises, le contenu ne réapparaissent soudainement. Il me semble que si Android est manquant d'une vue de mise à jour ici. J'ai aussi remarqué que lors du débogage avec la hiérarchie de la visionneuse, la sélection d'une vue sera toujours de la faire réapparaître, apparemment parce que la hiérarchie de la visionneuse forces de la vue sélectionnée à se redessiner.

Je ne pouvais pas faire ce travail par programme; d'invalider la liste de la vue ou de la totalité de la vue pager même, n'a eu aucun effet.

C'est avec la compatibilité v4_r7 de la bibliothèque. J'ai aussi essayé d'utiliser la dernière révision, puisqu'il prétend résoudre de nombreux problèmes liés à la vue de radiomessagerie, mais il encore aggravé la situation (par exemple, les gestes ont été brisées, de sorte qu'il ne serait pas me laisser défiler toutes les pages plus parfois.)

Est ce que quelqu'un d'autre en cours d'exécution dans ces questions, aussi, ou avez-vous une idée de ce qui pourrait être la cause?

46voto

stefano Points 903

Nous avons finalement réussi à trouver une solution. Apparemment, notre mise en œuvre a souffert de deux questions:

  1. notre carte n'a pas supprimé la vue en destroyItem().
  2. nous avons été la mise en cache des vues pour que nous ayons à gonfler notre disposition juste une fois, et, comme nous n'étions pas la suppression de la vue en destroyItem(), nous n'étions pas à l'ajouter en instantiateItem() mais juste de retour de la mise en cache de la vue correspondant à la position actuelle.

Je n'ai pas regardé trop profondément dans le code source de l' ViewPager - et ce n'est pas exactement explicite que vous avez à faire - mais les docs dit :

destroyItem()
Supprimer une page pour la position donnée. La carte est responsable de la suppression de la vue de son conteneur, mais il ne doit s'en assurer par le temps, elle retourne de finishUpdate(ViewGroup).

et:

Un très simple PagerAdapter peut choisir d'utiliser les pages Vues eux-mêmes comme des objets clés, de les renvoyer à partir de instantiateItem(ViewGroup, int) après la création et les ajouter à la ViewGroup parent. Un correspondant de destroyItem(ViewGroup, int, Object) de la mise en œuvre de supprimer l'Affichage de la ViewGroup parent et isViewFromObject(Vue, Objet) pourrait être mise en œuvre que le retour de la vue == objet;.

Donc, ma conclusion est qu' ViewPager s'appuie sur ses sous-jacente de l'adaptateur explicitement ajouter/supprimer ses enfants en instantiateItem()/destroyItem(). C'est, si votre carte est une sous-classe de PagerAdapter, votre sous-classe doit implémenter cette logique.

Note de côté: être conscient de ce que si vous utilisez des listes à l'intérieur d' ViewPager.

23voto

Ringen Points 131

J'ai eu exactement le même problème, mais j'ai en fait détruit la vue dans destroyItem (je pensais). Le problème était cependant que je l'ai détruit en utilisant viewPager.removeViewAt(index); insted of viewPager.removeView((View) object);

Faux:

 @Override
public void destroyItem(ViewGroup viewPager, int position, Object object) {
    viewPager.removeViewAt(position);
}
 

Droite:

 @Override
public void destroyItem(ViewGroup viewPager, int position, Object object) {
    viewPager.removeView((View) object);
}
 

11voto

Chris Banes Points 3013

ViewPager essaie de faire des choses intelligentes pour réutiliser des éléments, mais il vous oblige à renvoyer de nouvelles positions lorsque les choses ont changé. Essayez d’ajouter ceci à votre PagerAdapter:

 public int getItemPosition (Object object) { return POSITION_NONE; }
 

Il indique en gros à ViewPager que tout a changé (et le force à tout ré-instancier). C’est la seule chose à laquelle je peux penser spontanément.

1voto

Sparky Points 6181

Le Android Support Library a une démo de l'Activité, qui comprend un ViewPager avec une ListView sur chaque page. Vous devriez jeter un coup d'oeil et voir ce que ça donne.

Dans Eclipse (avec Android Outils de Dev r20):

  1. Sélectionnez New > Android Sample Project
  2. Sélectionnez votre cible API de niveau (je suggère la plus récente disponible)
  3. Sélectionnez Support4Demos
  4. Cliquez-droit sur le projet et sélectionnez Android Tools > Add Support Library
  5. Exécutez l'application et sélectionnez Fragment puis Pager

Le code est en src/com.example.android.supportv4.app/FragmentPagerSupport.java. Bonne chance!

0voto

Tim O'Brien Points 1715

J'ai couru dans le présent et avait des questions semblables. J'ai même demandé à un débordement de pile.

Pour moi, la mère de la mère de mon point de vue de quelqu'un sous-classé LinearLayout et emportait requestLayout() sans appelant super.requestLayout(). Cela a empêché onMeasure et onLayout soit appelé sur mon ViewPager (bien que hierarchyviewer manuellement les appelle). Sans être mesurée qu'ils vont afficher des vides dans ViewPager.

Afin de vérifier votre contenant des points de vue. Assurez-vous qu'ils sous-classe de la Vue et de ne pas aveuglément remplacer requestLayout ou quelque chose de semblable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X