Android Нажмите на список, пункт проверяет неправильный флажок - PullRequest
8 голосов
/ 25 октября 2010

Я создал собственный ListView, расширив SimpleCursorAdapter. Результат: ИЗОБРАЖЕНИЕ + CheckedTextView (Текст + Флажок).

Когда я долго щелкаю по пункту, все работает нормально - я получаю правильный идентификатор и подробную информацию о выбранном элементе.

Проблема возникает, когда я пытаюсь пометить элемент как отмеченный, но он устанавливает неправильный флажок.

Например: В моем списке 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);
                }

            }
        });

Ценю любую помощь!

Дайте мне знать, если вам нужно, чтобы я отправил больше кода.

Спасибо!

Кстати, если я нажму более чем на одну ... ПАРТИЯ продолжается ... нет очевидного порядка ...

РЕДАКТИРОВАТЬ: Адаптер код

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

1 Ответ

11 голосов
/ 25 октября 2010

Майра права - проблема связана с тем, как ListView повторно использует ваши представления.Это не так, как будто есть 9 экземпляров объекта CheckedTextView, по одному на просмотр.Вместо этого есть один, который повторно используется во всех строках.Таким образом, вы не можете полагаться на объект 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);
}

Это должно решить вашу проблему.Альтернативный подход заключается в перемещении логики того, проверена ли строка или нет, в объект домена, который представляет строка.Это было бы моим предпочтением.

...