J'ai donc ce problème que j'avais avant, et naturellement j'ai demandé de l'aide ici . La réponse de Luksprog était excellente car je n'avais aucune idée de la façon dont ListView et GridView s'optimisaient avec le recyclage des vues. Ainsi, avec ses conseils, j'ai pu changer la façon dont j'ai ajouté des vues à mon GridView. Le problème est maintenant que j'ai quelque chose qui n'a pas de sens. C'est mon getView
de mon BaseAdapter
:
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
convertView = inflater.inflate(R.layout.day_view_item, parent, false);
}
Log.d("DayViewActivity", "Position is: "+position);
((TextView)convertView.findViewById(R.id.day_hour_side)).setText(array[position]);
LinearLayout layout = (LinearLayout)convertView.findViewById(R.id.day_event_layout);
//layout.addView(new EventFrame(parent.getContext()));
TextView create = new TextView(DayViewActivity.this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 62, getResources().getDisplayMetrics()), 1.0f);
params.topMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
params.bottomMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
create.setLayoutParams(params);
create.setBackgroundColor(Color.BLUE);
create.setText("Test");
//the following is my original LinearLayout.LayoutParams for correctly setting the TextView Height
//new LinearLayout.LayoutParams(0, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, getResources().getDisplayMetrics()), 1.0f)
if(position == 0) {
Log.d("DayViewActivity", "This should only be running when position is 0. The position is: "+position);
layout.addView(create);
}
return convertView;
}
}
Le problème est que lorsque je fais défiler, cela se produit, et pas sur la position 0 ... On dirait la position 6 et la position 8, plus cela en met deux en position 8. Maintenant, j'essaie toujours de maîtriser l'utilisation de ListView et de GridView, alors je le fais pas comprendre pourquoi cela se produit. L'une des principales raisons pour lesquelles je pose cette question est d'aider d'autres personnes qui ne connaissent probablement pas la vue de recyclage de ListView et de GridView, ou la façon dont cet article le dit, le mécanisme ScrapView.
Modifier plus tard
Ajouter un lien vers une discussion Google IO qui est essentiellement tout ce dont vous avez besoin pour comprendre le fonctionnement de ListView. Link était mort dans l'un des commentaires. Donc user3427079 était assez gentil pour mettre à jour ce lien. Ici, c'est pour un accès facile.
0
).ListView
besoin d'une nouvelle ligne à afficher (comme continuer à faire défiler vers le bas / vers le haut). Le problème est que la vue qui vient de disparaître et qui sera utilisée aux futurs postes nécessaires aTextView
déjà ajouté, c'est le problème. Pour le résoudre, vous devez le supprimer dans lagetView
méthode si lagetView
méthode est appelée pour une autre position que0
.Réponses:
Au départ, je n'étais pas non plus au courant du recyclage de listview et du mécanisme d'utilisation de convertview, mais après une journée entière de recherche, je comprends assez bien les mécanismes de la vue liste en faisant référence à une image d' android.amberfog
Chaque fois que votre vue de liste est remplie par un adaptateur, cela montre essentiellement le nombre de lignes que la vue de liste peut afficher à l'écran et le nombre de lignes n'augmente pas même lorsque vous faites défiler la liste. C'est l'astuce qu'utilise Android pour que la vue de liste fonctionne plus efficacement et plus rapidement. Maintenant, l'histoire interne de listview se référant à l'image, comme vous pouvez le voir, initialement la listview a 7 éléments visibles, puis, si vous faites défiler vers le haut jusqu'à ce que l'élément 1 ne soit plus visible, getView () passe cette vue (c'est-à-dire élément1) au recycleur et vous pouvez utiliser
à l'intérieur de votre
Vous remarquerez dans votre logcat, initialement, convertview est nul pour toutes les lignes visibles, car initialement il n'y avait pas de vues (c'est-à-dire d'éléments) dans le recycleur, donc votre getView () crée une nouvelle vue pour chacun des éléments visibles, mais le dès que vous faites défiler vers le haut et que l'élément 1 sort de l'écran, il sera envoyé au recycleur avec son état actuel (par exemple le `` texte '' TextView ou dans le mien, si la case est cochée, il sera associé à la vue et stocké dans un recycleur).
Maintenant, lorsque vous faites défiler vers le haut / bas, votre liste ne va pas créer une nouvelle vue, elle utilisera la vue qui est dans votre recycleur. Dans votre Logcat, vous remarquerez que le 'convertView' n'est pas nul, c'est parce que votre nouvel élément 8 sera dessiné à l'aide de convertview, c'est-à-dire qu'il prend essentiellement la vue de l'élément 1 du recycleur et gonfle l'élément 8 à sa place, et vous pouvez observer cela dans mon code. Si vous aviez une case à cocher et si vous la cochez à la position 0 (disons que l'élément 1 avait une case à cocher et que vous l'avez cochée) alors lorsque vous faites défiler vers le bas, vous verrez la case à cocher de l'élément 8 déjà cochée, c'est pourquoi la vue de liste utilise la même vue, ne pas créer de nouveau pour vous en raison de l'optimisation des performances.
Choses importantes
1 . Ne réglez jamais le
layout_height
etlayout_width
de votre ListViewwrap_content
commegetView()
forcera votre adaptateur pour obtenir des enfants pour mesurer la hauteur des vues à tirer en vue de la liste et peut entraîner des comportements inattendus comme un retour convertview même la liste n'est pas scrolled.always utilisermatch_parent
ou fixes largeur hauteur.2 . Si vous souhaitez utiliser une mise en page ou vue après l' affichage de votre liste et pourrait question est venu dans votre esprit si je mets le
layout_height
àfill_parent
la vue après vue de la liste ne sera pas affiché comme il descend l'écran, il est donc préférable de mettre votre listview dans un Par exemple, mise en page linéaire et définissez la hauteur et la largeur de cette mise en page en fonction de vos besoins et définissez l' attribut de hauteur et de largeur de votre vue de liste à partir de votre mise en page (comme si votre largeur de mise en page est de 320 et la hauteur de 280), alors votre vue de liste devrait avoir la même hauteur et la même largeur. Cela indiquera à getView () la hauteur et la largeur exactes des vues à rendre, et getView () n'appellera pas encore et encore des lignes aléatoires, et d'autres problèmes comme le retour de la vue de conversion avant même que le défilement ne se produise, j'ai un test ceci moi-même, à moins que ma listview ne soit à l'intérieur de lineaLayout, cela posait également des problèmes tels que la répétition de l'appel de vue et la conversion de la vue en tant que, mettre Listview à l'intérieur de LinearLayout fonctionnait comme par magie pour moi (je ne savais pas pourquoi)Mais maintenant c'est résolu, je sais, je ne suis pas très doué pour expliquer, mais comme j'ai mis toute ma journée à comprendre, j'ai donc pensé que d'autres débutants comme moi peuvent obtenir de l'aide de mon expérience et j'espère que maintenant vous aurez un peu de compréhension de ListView cadre comment cela fonctionne, car il est vraiment en désordre et les débutants tricky donc trouvé trop de problème comprendre
la source
if you had a checkbox and if you check it at position 0(let say item1 has also a checkbox and you checked it) so when you scroll down you will see item 8 checkbox is already checked,this is why listview is re using the same view not creating a new for you due to performance optimization.
pour que je réalise mon erreur. Meilleur article sur le recyclage Android ListView que j'ai rencontré!RecyclerView
également sur le même mécanisme? Dans ma question stackoverflow.com/questions/47897770/… , je sais que la tâche est impossible aveclistView
. Dois-je essayer avecrecyclerView
?Attention, dans le modèle Holder, si vous définissez la position dans votre objet Holder, vous devez la définir à chaque fois, par exemple:
ceci est un exemple d'une classe abstraite, où
effectue toutes les opérations de réglage pour
la source
parent.setTag(holder);
au lieu de la manière correcte qui est,view.setTag(holder);
En utilisant le modèle Holder, vous pouvez obtenir ce que vous voulez:
Vous pouvez trouver la description de ce modèle ici:
Le recyclage de la vue de liste se produit lorsque vous faites défiler l'écran vers le bas et que les éléments de la vue de liste ci-dessus sont masqués. Ils sont réutilisés pour afficher de nouveaux éléments de vue de liste.
la source