Fehlerhafte Selektion in der Liste

B

Butch78

Neues Mitglied
0
Hi Leute,

mich macht meine ListView noch irre :crying:. Ich versuchte nun schon einige Zeit folgendes Problem zu lösen. Habe eine Liste der eine Textview liegt. Sobald ich ein Objekt anklicke, soll sich dessen Background ändern. Das klappt auch schon alles.

Aber Probleme gibt es wenn ich in meiner Liste scrollen muss. Wenn ich z.B. das erste Element selektiere und scrolle dann nach unten, ist auch automatisch das nächste sichtbare Element mit selektiert.

Hier mal mein Code:

Code:
[LEFT]public View getView(final int position, View convertView, ViewGroup parent) {
   View view = null;
   if (convertView == null) {
    LayoutInflater inflator = context.getLayoutInflater();
    view = inflator.inflate(R.layout.condiment_list_items, null);
    final ViewHolder viewHolder = new ViewHolder();
    //viewHolder.icon = (ImageView)view.findViewById(R.id.iv_loeschen_icon);
    viewHolder.text = (TextView) view.findViewById(R.id.tx_condiment_list_items);      
    viewHolder.text.setTag(list.get(position));   
    viewHolder.text.setBackgroundDrawable(null);
    viewHolder.text.setOnClickListener(new OnClickListener() {    
     @Override   
     public void onClick(View v) {     
      BasketItem item = (BasketItem) 
        v.getTag();
      if(item.getKorb() == 0){
       item.setKorb(1);
       v.setBackgroundDrawable(getResources().getDrawable(R.drawable.strike_out));
       Toast.makeText(mContext, item.getZutat(), Toast.LENGTH_LONG).show();
      }else{
       item.setKorb(0);
       v.setBackgroundDrawable(null);
      }             
     }
    });
    
  
    viewHolder.text.setOnLongClickListener(new OnLongClickListener() {    
     @Override
     public boolean onLongClick(View v) {
      ArrayList<BasketItem> list = new ArrayList<BasketItem>();
      BasketItem item = (BasketItem)  viewHolder.text.getTag();
      list.add(item);
      Intent intent = new Intent(mContext, ContextMenuHelperCondimentList.class);
      intent.putParcelableArrayListExtra ("list", (ArrayList<? extends Parcelable>) list); 
      startActivity(intent);
      return true;
     }
    });
    view.setTag(viewHolder);
    viewHolder.text.setTag(list.get(position));
    
    if(list.get(position).getKorb()==1){
     viewHolder.text.setBackgroundDrawable(getResources().getDrawable(R.drawable.strike_out));
    }else{
     viewHolder.text.setBackgroundDrawable(null);
    }   
    
   } else {
    view = convertView;
   }
   ViewHolder holder = (ViewHolder) view.getTag();
   holder.text.setText(list.get(position).getZutat());
   holder.text.setTypeface(mFontNormal);
   return view;
  }
 }

Viele Grüße

Butch
[/LEFT]
 
Zuletzt bearbeitet:
Keiner eine Idee?

Gruß
 
Der View wird wiederverwendet.Änderst du also die Hintergrundfarbe, so musst du dafür sorgen, dass sie wieder zurückgeändert wird in getView().

PS: Formatiere doch die Codeschnipsel nächstes mal für bessere Lesbarkeit.
 
Hi,

sorry hast Recht da muss ich besser aufpassen...

Was genau meinst du das mit zurücksetzen in getView? Per Googlesuche hatte ich irgendwo das gleiche Problem gefunden und dort wurde gesagt mal sollte den Hintergrund in getView auf null setzen. Das habe ich bereits drin und hat aber leider keine Auswirkung gezeigt:

Code:
[SIZE=2][LEFT]viewHolder.text.setBackgroundDrawable(null);
    viewHolder.text.setOnClickListener(new OnClickListener() {    
     @Override   
     public void onClick(View v) {     
      BasketItem item = (BasketItem) 
        v.getTag();
      if(item.getKorb() == 0){
       item.setKorb(1);
       v.setBackgroundDrawable(getResources().getDrawable(R.drawable.strike_out));
      }else{
       item.setKorb(0);
       v.setBackgroundDrawable(null);
      }             
     }
    });[/SIZE][/LEFT]
[SIZE=2]
[/SIZE]


Gruß
Butch
 
else {
view = convertView;
}

das Ding kurz vor dem Ende mein er. Wenn eine View aus dem sichtbaren Bereich rauskommt, kriegst du sie in getView als convertView wieder zum recyclen.
Du setzt kurz vor Ende von getView die alte View als neue View ein die du dann zurücklieferst ohne nochmal die Hintergrundfarbe zu ändern. Wenn also die alte View die zum recyclen ankommt und eine Hintergrundfarbe gesetzt hat läuft sie unverändert durch dein Code durch.
 
Hi,

danke soweit. Jetzt werden zwar keine doppelten Items mehr selektiert, aber jetzt gehen beim scrollen leider die bereits ausgewählten Items verloren. Ich setze nun den Hintergrund der alten view zurück und übergebe die alte view dann der neuen.

else​
{
ViewHolder holder = (ViewHolder) convertView.getTag();
holder.
text.setBackgroundDrawable(null);
view = convertView;

}

Effekt nun: Ich selektiere das erste Element und scroller runter und wieder hoch => erstes Element hat die Selektion verloren.

Gruß


 
OK, langsam zum mitschreiben:
Der View wird recycled!

DU musst dich darum kümmern, dass die Farbe für die Selektion in getView() richtig gesetzt wird und zwar für "selektiert" UND für "nicht selektiert".

Woher soll das System es sonst wissen, wenn du es ihm nicht mitteilst?
 
Das mach ich doch schon: In meinem Clicklistener nehm ich mir das passende Element aus meiner ArrayListe und setze entsprechend den Status ( item.setKorb(0/1). Diesen Status frage ich weiter unten wieder ab und setze den Hintergrund.

Code:
public void onClick(View v) {          [SIZE=2]
      BasketItem item = [/SIZE][SIZE=2][COLOR=#0000c0][SIZE=2][COLOR=#0000c0]mBasketList[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2].get(position);
[/SIZE]      if(item.getKorb() == 0){
       item.setKorb(1);
       v.setBackgroundDrawable(getResources().getDrawable(R.drawable.strike_out));
       Toast.makeText(mContext, item.getZutat(), Toast.LENGTH_LONG).show();
      }else{
       item.setKorb(0);
       v.setBackgroundDrawable(null);
      }             
     }


Code:
[SIZE=2] 
[LEFT]BasketItem item = [/SIZE][SIZE=2][COLOR=#0000c0][SIZE=2][COLOR=#0000c0]mBasketList[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2].get(position);
[/SIZE][B][SIZE=2][COLOR=#7f0055][SIZE=2][COLOR=#7f0055]if[/B][/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2](item.getKorb()==1){
       viewHolder.[/SIZE][SIZE=2][COLOR=#0000c0][SIZE=2][COLOR=#0000c0]text[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2].setBackgroundDrawable(getResources().getDrawable  (R.drawable.[/SIZE][I][SIZE=2][COLOR=#0000c0][SIZE=2][COLOR=#0000c0]strike_out[/I][/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]));
}[/SIZE][B][SIZE=2][COLOR=#7f0055][SIZE=2][COLOR=#7f0055]else[/B][/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]{
      viewHolder.[/SIZE][SIZE=2][COLOR=#0000c0][SIZE=2][COLOR=#0000c0]text[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2].setBackgroundDrawable([/SIZE][B][SIZE=2][COLOR=#7f0055][SIZE=2][COLOR=#7f0055]null[/B][/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]);
} [/LEFT]

[/SIZE]
 
dann mach statt null mal nen echten wert ( transparent vielleicht )

vielleicht wird null ja einfach ignoriert ?
 
Butch78 schrieb:
Das mach ich doch schon: In meinem Clicklistener nehm ich mir das passende Element aus meiner ArrayListe und setze entsprechend den Status ( item.setKorb(0/1). Diesen Status frage ich weiter unten wieder ab und setze den Hintergrund.
Nein, du setzt den Hintergrund nur wenn der convertView == null ist.
Respektive fragst du deinen Korb nur ab wenn der convertView null ist, wenn er != null ist dann wird der Hintergrund einfach zurückgesetzt.
 
Sorry Leute aber es will einfach nicht... Tut mir leid wenn ich euch schon nerve, aber ich weiß echt nicht weiter:

hier mein aktueller Code:

Code:
 public View getView(final int position, View convertView, ViewGroup parent) {
   View view = null;
   if (convertView == null) {
    LayoutInflater inflator = context.getLayoutInflater();
    view = inflator.inflate(R.layout.condiment_list_items, null);
    final ViewHolder viewHolder = new ViewHolder();
    //viewHolder.icon = (ImageView)view.findViewById(R.id.iv_loeschen_icon);
    viewHolder.text = (TextView) view.findViewById(R.id.tx_condiment_list_items);      
    viewHolder.text.setTag(list.get(position));   
    viewHolder.text.setOnClickListener(new OnClickListener() {    
     @Override   
     public void onClick(View v) {     
      BasketItem item = mBasketList.get(position);
      if(item.getKorb() == 0){
       item.setKorb(1);
       v.setBackgroundDrawable(getResources().getDrawable(R.drawable.strike_out));
      }else{
       item.setKorb(0);
       v.setBackgroundColor(0x00000000); 
      }             
     }
    });
 
 
    viewHolder.text.setOnLongClickListener(new OnLongClickListener() {    
     @Override
     public boolean onLongClick(View v) {
      ArrayList<BasketItem> list = new ArrayList<BasketItem>();
      BasketItem item = (BasketItem)  viewHolder.text.getTag();
      list.add(item);
      Intent intent = new Intent(mContext, ContextMenuHelperCondimentList.class);
      intent.putParcelableArrayListExtra ("list", (ArrayList<? extends Parcelable>) list); 
      startActivity(intent);
      return true;
     }
    });
    view.setTag(viewHolder);    
    viewHolder.text.setTag(list.get(position));  
    BasketItem item = (BasketItem) 
      viewHolder.text.getTag();  
    if(item.getKorb()==1){
     viewHolder.text.setBackgroundDrawable(getResources().getDrawable(R.drawable.strike_out));
    }else{
     viewHolder.text.setBackgroundColor(0x00000000); 
    }       
   } else {
    view = convertView;    
    ViewHolder holder = (ViewHolder) view.getTag();
    BasketItem item = mBasketList.get(position); 
    if(item.getKorb()==0){
     holder.text.setBackgroundColor(0x00000000);  
    }else{
     holder.text.setBackgroundDrawable(getResources().getDrawable(R.drawable.strike_out));
    }
   }
   ViewHolder holder = (ViewHolder) view.getTag();
   holder.text.setTag(list.get(position));   
   holder.text.setText(list.get(position).getZutat());
   holder.text.setTypeface(mFontNormal);
   return view;
  }
 }

Ich prüfe den Status wenn convertView == null und umgekehrt, aber das Scrollproblem besteht weiterhin. Was mir beim debuggen gerade aufgefallen ist, das nach dem Scrollen:

BasketItem item = mBasketList.get(position); in meiner
onClick Methode nicht das richtige Element gibt. position scheint hier nicht zu stimmen...

Gruß
 
Ok ich glaube mit
BasketItem item = (BasketItem) viewHolder.​
text

.getTag();

in der onClick-Methode gehts nun...

Danke euch noch für eure Unterstützung:thumbup:
 
Ok, hier mal die richtige Variante:

Code:
public View getView(final int position, View convertView, ViewGroup parent) {
   View view = null;
   if (convertView == null) {
    LayoutInflater inflator = context.getLayoutInflater();
    view = inflator.inflate(R.layout.condiment_list_items, null);
    final ViewHolder viewHolder = new ViewHolder();
    //viewHolder.icon = (ImageView)view.findViewById(R.id.iv_loeschen_icon);
    viewHolder.text = (TextView) view.findViewById(R.id.tx_condiment_list_items);      
    viewHolder.text.setTag(list.get(position));   
    [color=red]//Die Listener werden nur bei einem neuen View angehängt, [b]SIE WERDEN RECYCLED![/b][/color]
    view.setTag(viewHolder);    
    viewHolder.text.setTag(list.get(position));  
    BasketItem item = (BasketItem) 
      viewHolder.text.getTag();  
    [color=red]//if anweisung hier weg[/color]
   } else {
    view = convertView;    
    ViewHolder holder = (ViewHolder) view.getTag();
    BasketItem item = mBasketList.get(position); 
    [color=red]//if Anweisung hier ist unnütz[/color]
   }
   [color=green]//if Anweisung hier hin
   if(item.getKorb()==1){
     viewHolder.text.setBackgroundDrawable(getResources().getDrawable(R.drawable.strike_out));
    }else{
     viewHolder.text.setBackgroundColor(0x00000000); 
    }       
    //Ausserdem müssen hier noch die Listener hin
[/color]

   ViewHolder holder = (ViewHolder) view.getTag();
   holder.text.setTag(list.get(position));   
   holder.text.setText(list.get(position).getZutat());
   holder.text.setTypeface(mFontNormal);
   return view;
  }
 }
 

Ähnliche Themen

Jansenwilson
Antworten
1
Aufrufe
691
Mazuch
Mazuch
M
Antworten
3
Aufrufe
163
moin
M
S
Antworten
33
Aufrufe
2.669
Sempervivum
S
Zurück
Oben Unten