Android Cliccare sulla casella di controllo sbagliato listItem controlli
-
25-09-2019 - |
Domanda
Ho creato un controllo ListView personalizzata estendendo SimpleCursorAdapter. Il risultato è IMAGE + CheckedTextView (Testo + Casella di controllo).
Quando ho tempo clic su un elemento, tutto funziona bene -. Ho l'ID a destra e il dettaglio della voce è fatto clic
Il problema si verifica quando si tenta di contrassegnare un elemento come controllato, ma controlla la casella sbagliata.
Ad esempio: Ho 9 articoli sulla mia lista, ordinato 1-9. se clicco su listItem 1, la casella di controllo sulla linea 9 viene controllato. se clicco sul punto 4, la casella di controllo sulla linea 6 viene controllata e se clicco sulla linea di mezzo, viene controllato.
Chiaramente mi manca qualcosa qui :) Mi ricordo quando ho tempo Fare clic sulla linea (contextMenu si apre), tutto funziona alla grande.
Questo è l'ascoltatore:
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
CheckedTextView markedItem = (CheckedTextView) view.findViewById(R.id.btitle);
if (!markedItem.isChecked()) {
markedItem.setChecked(true);
} else {
markedItem.setChecked(false);
}
}
});
Apprezzo tutto l'aiuto!
Fammi sapere se hai bisogno di me per pubblicare più codice.
Grazie!
A proposito, se clicco su più di uno ... la festa continua ... nessun ordine ovvio ...
EDIT: il codice adattatore
public class ImageCursorAdapter extends SimpleCursorAdapter {
private Cursor c;
private Context context;
private String url;
private TextView bUrl;
public ImageCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
this.c = c;
this.context = context;
}
public View getView(int pos, View inView, ViewGroup parent) {
View v = inView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.image_list, null);
}
this.c.moveToPosition(pos);
final TextView bTitle = (TextView) v.findViewById(R.id.btitle);
String bookmark = this.c.getString(this.c.getColumnIndex(Browser.BookmarkColumns.TITLE));
byte[] favicon = this.c.getBlob(this.c.getColumnIndex(Browser.BookmarkColumns.FAVICON));
if (favicon != null) {
ImageView iv = (ImageView) v.findViewById(R.id.bimage);
iv.setImageBitmap(BitmapFactory.decodeByteArray(favicon, 0, favicon.length));
}
bTitle.setText(bookmark);
return (v);
}
}
Soluzione
Mayra è giusto - il problema ha a che fare con il modo in cui il ListView è riutilizzando le vostre opinioni. Non è come se ci sono 9 le istanze dell'oggetto CheckedTextView
, uno per view. Invece, c'è un singolo che viene riutilizzato in tutte le righe. Così non si può contare sull'oggetto CheckedTextView per contenere lo stato di se un elemento è selezionato. Avrete bisogno di qualche struttura dati aggiuntivi per tenere se una determinata riga è selezionata, per esempio,
ArrayList<Boolean> checkedStates = new ArrayList<Boolean>();
Quando l'elemento ith
è vero se e solo se la riga ith
deve essere controllato. Poi all'interno del vostro itemClickListener:
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
boolean currentlyChecked = checkedStates.get(position);
checkedStates.set(position, !currentlyChecked);
// Refresh the list
}
});
Poi all'interno del codice di vista:
public View getView(int pos, View inView, ViewGroup parent) {
View v = inView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.image_list, null);
}
this.c.moveToPosition(pos);
final TextView bTitle = (TextView) v.findViewById(R.id.btitle);
String bookmark = this.c.getString(this.c.getColumnIndex(Browser.BookmarkColumns.TITLE));
byte[] favicon = this.c.getBlob(this.c.getColumnIndex(Browser.BookmarkColumns.FAVICON));
if (favicon != null) {
ImageView iv = (ImageView) v.findViewById(R.id.bimage);
iv.setImageBitmap(BitmapFactory.decodeByteArray(favicon, 0, favicon.length));
}
bTitle.setText(bookmark);
// Change the state of the checkbox to match that of the row's checked state.
// This check box item is reused for every row, so we need to reset its state each
// time the row is rendered.
CheckedTextView markedItem = (CheckedTextView) view.findViewById(R.id.btitle);
markedItem.setChecked(checkedStates.get(pos));
return (v);
}
Questo dovrebbe risolvere il problema. Un approccio alternativo sarebbe quello di spostare la logica se la riga è selezionata o meno nell'oggetto dominio che la riga rappresenta. Questa sarebbe la mia preferenza.