Pergunta

Eu criei um ListView personalizado, estendendo o SimpleCurSorAdapter. O resultado é Image + CheckEdTextView (Texto + Caixa de seleção).

Quando clico por muito tempo em um item, tudo funciona bem - recebo o ID e os detalhes certos do item clicado.

O problema ocorre quando tento marcar um item como verificado, mas ele verifica a caixa de seleção errada.

Por exemplo: Eu tenho 9 itens na minha lista, classificados por 1-9. Se eu clicar no ListItem 1, a caixa de seleção na linha 9 estará sendo verificada. Se eu clicar no item 4, a caixa de seleção na linha 6 estará sendo verificada e, se eu clicar na linha do meio, ele estará sendo verificado.

Claramente estou perdendo alguma coisa aqui :) Lembre -se de quando clico há muito tempo na linha (o contextmenu abre), tudo funciona muito bem.

Este é o ouvinte:

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

            }
        });

Aprecie qualquer ajuda!

Deixe -me saber se você precisar que eu poste mais código.

Obrigada!

BTW, se eu clicar em mais de um ... a festa continua ... sem ordem óbvia ...

Editar: o código do 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);
    }
}
Foi útil?

Solução

Mayra está certa - o problema tem a ver com a maneira como a ListView está reutilizando suas opiniões. Não é como se houvesse 9 instâncias do CheckedTextView objeto, um por visualização. Em vez disso, há um único que é reutilizado em todas as linhas. Portanto, você não pode confiar no objeto CheckEdTextView para manter o estado de se um item é verificado. Você precisará de alguma estrutura de dados adicional para sustentar se uma determinada linha é verificada, por exemplo,

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

Onde o ith elemento é verdadeiro se o ith A linha deve ser verificada. Então, dentro do seu 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
        }
    });

Então, dentro do seu código de visualização:

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

Isso deve resolver seu problema. Uma abordagem alternativa seria mover a lógica de se a linha é verificada ou não para o objeto de domínio que a linha representa. Essa seria minha preferência.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top