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);
    }
}
È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top