8

SimpleCursorAdapter を拡張してカスタム ListView を作成しました。結果は IMAGE + CheckedTextView (テキスト + チェックボックス) です。

アイテムを長押しすると、すべて正常に動作します。クリックしたアイテムの正しい ID と詳細を取得します。

アイテムをチェック済みとしてマークしようとすると問題が発生しますが、間違ったチェックボックスがチェックされます。

例:リストに 9 つの項目があり、1 から 9 の順に並べ替えられています。listItem 1 をクリックすると、9 行目のチェックボックスがチェックされます。項目 4 をクリックすると、6 行目のチェックボックスがチェックされ、中央の行をクリックするとチェックされます。

明らかに、ここに何かが欠けています:)行を長押しすると(contextMenuが開きます)、すべてがうまく機能します。

これはリスナーです:

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

            }
        });

どんな助けにも感謝します!

さらにコードを投稿する必要がある場合はお知らせください。

ありがとうございました!

ところで、複数をクリックすると... PARTYが続きます...明らかな順序はありません...

編集: アダプタ コード

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

1 に答える 1

11

Mayraは正しいです-問題は、ListViewがビューを再利用する方法に関係しています。CheckedTextViewビューごとに1つずつ、オブジェクトのインスタンスが9つあるわけではありません。代わりに、すべての行で再利用される単一のものがあります。したがって、CheckedTextViewオブジェクトを使用して、アイテムがチェックされているかどうかの状態を保持することはできません。特定の行がチェックされているかどうかを保持するために、いくつかの追加のデータ構造が必要になります。たとえば、

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

ith要素がtrueの場合、行ithをチェックする必要があります。次に、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
        }
    });

次に、ビューコード内で:

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

これで問題が解決するはずです。別のアプローチは、行がチェックされるかどうかのロジックを、行が表すドメインオブジェクトに移動することです。それが私の好みです。

于 2010-10-24T23:49:55.087 に答える