Pregunta

He creado un ListView personalizada extendiendo SimpleCursorAdapter. El resultado es una imagen + CheckedTextView (Texto + casilla de verificación).

Cuando a largo clic en un elemento, todo funciona bien -. Me da la ID derecha y detalles del artículo se ha hecho clic

El problema se produce cuando trato de marcar un elemento como equipaje pero comprueba la casilla equivocada.

Por ejemplo: tengo 9 artículos en mi lista, ordenados 1-9. si hago clic en listitem 1, se marca la casilla en la línea 9. si hago clic en el punto 4, se marca la casilla en la línea 6 y si hago clic en la línea media, que se está comprobando.

Es evidente que me falta algo aquí :) Me acuerdo cuando me clic largo de la línea (contextMenu abre), todo funciona muy bien.

Este es el oyente:

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);
                }

            }
        });

agradecería cualquier ayuda!

Avísame Si me necesita para publicar más código.

Gracias!

Por cierto, si hago clic en más de un ... La fiesta continúa ... sin un orden obvio ...

EDIT: el código de adaptador

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);
    }
}
¿Fue útil?

Solución

Mayra es correcto - el problema tiene que ver con la forma en que el ListView está volviendo a usar los puntos de vista. No es como si hay 9 instancias del objeto CheckedTextView, uno por cada punto de vista. En su lugar, hay una sola que se reutiliza en todas las filas. Por lo tanto no se puede confiar en el objeto CheckedTextView para mantener el estado de si se comprueba un elemento. Usted necesitará algún tipo de estructura de datos adicionales para sostener si una fila dada se comprueba, por ejemplo,

ArrayList<Boolean> checkedStates = new ArrayList<Boolean>();

Cuando el elemento de ith es cierto si y sólo si la fila ith debe ser revisado. Luego, dentro de su 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
        }
    });

A continuación, dentro de su código de la 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);
}

Esto debería resolver su problema. Un enfoque alternativo sería mover la lógica de si la fila está marcada o no en el objeto de dominio que la fila representa. Ese sería mi preferencia.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top