J'utilise un arrayadapter pour une liste de mon propre type d'objets (un seul type) et je donne à l'utilisateur une option pour créer plus d'éléments (créant ainsi plus de vues pour ces éléments). À un moment donné, GeveView a envoyé un nouvel indice "Position" avec une "convertie" non nulle. Il montre ensuite la première vue dans la dernière position. Après cela, lors du défilement des vues, tout mélangez-vous. Je suppose que cela signifie que j'ai manipulé les points de vue d'une manière que je ne devrais pas avoir, mais je ne vois tout simplement pas où. Voici un code:
@Override public View getView(int position, View convertView, ViewGroup parent) { View v; PreviewItemHolder holder = null; // Initialize view if convertview is null if (convertView == null) { v = newView(parent, position); } // Populate from previously saved holder else { // Use previous item if not null v = convertView; } // Populate if the holder is null (newly inflated view) OR // if current view's holder's flag is true and requires populating if ((holder == null) || (holder.readPopulateFlag())) { bindView(position, v); } return v; } private View newView(ViewGroup parent, int position) { // Getting view somehow... LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); View inflatedView = inflater.inflate(R.layout.preview_element_set, parent, false); PreviewItemHolder holder = new PreviewItemHolder(); holder.set = (Set) mSets.get(position); holder.previewElementHolders = new ArrayList<PreviewElementHolder>(); holder.expandArea = (View) inflatedView.findViewById(R.id.expandArea); holder.repetitionsLabel = (TextView) inflatedView.findViewById(R.id.previewRepetitionsInput); holder.endlessInput = (CheckBox) inflatedView.findViewById(R.id.previewSetEndlessInput); holder.nameLabel = (TextView) inflatedView.findViewById(R.id.previewSetNameLabel); holder.commentInput = (EditText) inflatedView.findViewById(R.id.previewSetCommentInput); holder.soundInput = (EditText) inflatedView.findViewById(R.id.previewSetSoundInput); holder.addElementButton = (Button) inflatedView.findViewById(R.id.previewSetAddElements); holder.expand = (View) inflatedView.findViewById(R.id.infoArea); holder.collapse = (View) inflatedView.findViewById(R.id.collapse); final int setsLength = holder.set.getElements().size(); for (int i = 0; i < setsLength; i++) { AElement currElement = holder.set.getElements().get(i); // Creating new element holder according to the type if (currElement instanceof Rest) { holder.previewElementHolders.add(new PreviewRestHolder()); } else if (currElement instanceof TimeExercise) { holder.previewElementHolders.add(new PreviewTimeExerciseHolder()); } else if (currElement instanceof RepetitionExercise) { holder.previewElementHolders.add(new PreviewRepetitionExerciseHolder()); } View currLayout = inflateElement(currElement, inflater, i, holder.previewElementHolders.get(i)); // Add the child before the hairline, collapse image and the add // button // (3 last children of the expandArea view ((ViewGroup) holder.expandArea).addView(currLayout, ((ViewGroup) holder.expandArea).getChildCount() - CHILDREN_INDEX_AFTER_PHASES_LABEL); } inflatedView.setTag(holder); return inflatedView; } private void bindView(int position, View inflatedView) { final PreviewItemHolder holder = (PreviewItemHolder) inflatedView.getTag(); holder.set.setId(position); holder.endlessInput.setChecked(holder.set.getEndless()); holder.soundInput.setText(holder.set.getSound()); holder.nameLabel.setText(holder.set.getName()); holder.commentInput.setText(holder.set.getComment()); // Make sure there is a name. If none, put default if (holder.nameLabel.getText().equals("")) { holder.nameLabel.setText(R.string.default_set_name); } // Set repetitions value according to the endless flag if (holder.set.getEndless()) { holder.repetitionsLabel.setText(R.string.infinity); } else { holder.repetitionsLabel.setText(String.valueOf(holder.set.getRepetitions())); } // Set click listeners holder.endlessInput.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { // Save endless flag holder.set.setEndless(isChecked); // If an endless set - Dropset if (isChecked) { holder.repetitionsLabel.setText(R.string.infinity); } else { // Regular set holder.repetitionsLabel.setText(String.valueOf(holder.set.getRepetitions())); } hideShowRepsWeights(holder); } }); holder.repetitionsLabel.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { NumericDialog instance = NumericDialog.newInstance(holder, holder.set, NumericDialog.INTEGER_MODE, Consts.SET_REPETITIONS_METHOD_NAME); instance.show(((Activity) getContext()).getFragmentManager(), null); } }); holder.nameLabel.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // Setting flag to true to allow populating this view holder.rePopulateFlag = true; SetNameDialog instance = SetNameDialog.newInstance(holder.set); instance.show(((Activity) getContext()).getFragmentManager(), null); } }); holder.commentInput.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { // After focus is lost, save the text into the set holder.set.setComment(holder.commentInput.getText().toString()); } } }); // TODO Change that into a dialog that allows selection of sounds holder.soundInput.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { // After focus is lost, save the text into the set holder.set.setSound(holder.soundInput.getText().toString()); } } }); holder.expand.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // Change visibility - Show expandArea and its data holder.expandArea.setVisibility(View.VISIBLE); holder.expand.setVisibility(View.GONE); holder.collapse.setVisibility(View.VISIBLE); } }); holder.collapse.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // Change visibility - Hide expandArea and its data holder.expandArea.setVisibility(View.GONE); holder.collapse.setVisibility(View.GONE); holder.expand.setVisibility(View.VISIBLE); } }); holder.addElementButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { AddElementDialog instance = AddElementDialog.newInstance(holder); instance.show(((Activity) getContext()).getFragmentManager(), null); } }); // Populate elements for (PreviewElementHolder elementHolder : holder.previewElementHolders) { populateElement(elementHolder, holder); } // Finally hide/show if needed - Should this be put somewere else? hideShowRepsWeights(holder); }
3 Réponses :
Vous devez appeler Checkout ce javadoc pour plus de détails. P> Bindview () Code> Toujours fort>. L'idée ou la réutilisation est comme suit. Si
convertiview code> est NULL, vous créez et initialise une nouvelle vue. Si
convertiview code> n'est pas NULL, vous prenez cette vue et convert em> il est neuf, ce qui signifie que vous appelez
liaitview () code> avec
convertview code> instance. p>
J'ai essayé mais cela n'a pas résolu le problème. Même lorsque j'appelle Bindview () à chaque fois, le problème se produit toujours de la même manière qu'elle l'a fait auparavant. Je ne pense pas que vous devez ré-régler les données de Converview à chaque fois pour résoudre ce problème.
Un ami m'a expliqué le problème et maintenant, il semble fonctionner. Fondamentalement, ListView contient un petit nombre de vues et les recycle tout le temps. Dans mon cas, j'ai un Nexus 4 et il semble donc avoir 7 points de vue total car le 8 a toujours été celui qui a commencé à causer des problèmes. Ce que j'avais manqué dans mon getsView () était une condition vérifiant la corrélation entre la position et l'ID de l'élément actuel dans le tableau ArrayAdapter. Voici comment il semble maintenant que cela fonctionne:
@Override public View getView(int position, @Nullable View convertView, ViewGroup parent) { View v; PreviewItemHolder holder = null; // Initialize view if convertview is null if (convertView == null) { v = newView(parent, position); } // Populate from previously saved holder else { // If position and id of set do not match, this view needs to be re-created, not recycled if (((PreviewItemHolder) convertView.getTag()).set.getId() != position) { v = newView(parent, position); } else { // Use previous item if not null v = convertView; // Get holder holder = (PreviewItemHolder) v.getTag(); } } // Populate if the holder is null (newly inflated view) OR // if current view's holder's flag is true and requires populating if (holder == null || holder.readPopulateFlag()) { bindView(position, v); } return v; }
J'avais exactement le même problème avec un fondeaderapter, mais mon cerveau ne peut pas prendre cela ... Je sais que c'était il y a longtemps, mais avez-vous d'autres explications expliquées pourquoi cela a aidé? Cela m'a aussi aidé, je ne comprends tout simplement pas ...
C'est excellent. Le même problème est arrivé avec moi lorsque j'utilisais 3 types de mises en page différents dans mon listview code>. Dès que la vue supérieure est de type 1 et la vue suivante pour entrer à l'écran est d'un autre type,
convertiview code> NULL et une vue erronée a été recyclée à l'aide de
gettag code>.
Lorsque vous avez plusieurs types de vues qui doivent être recyclés, vous devez indiquer à la liste de voir le nombre de types que vous avez en implémentant la méthode
@Override public int getViewTypeCount() { return 7; }
Qu'est-ce que tituly.readpopollateflag () ??