Игра "Ударь по флажку" с ListView - PullRequest
0 голосов
/ 02 сентября 2010

У меня есть ListActivity, который изначально использовал ArrayAdapter. Каждый элемент в моем ListView содержит флажок.

Я изменил Адаптеры на CursorAdapter. Все работает нормально, кроме флажков вышли из-под контроля. Например: когда я нажимаю флажок в позиции 1, флажок в позиции 4 проверяется. Если я снова установлю флажок в позиции 1, он проверит (т. Е. Когда я установлю флажок в позиции 1, если флажок в позиции 4 не установлен, флажок в позиции 4 будет отмечен, в противном случае флажок в позиции 1 проверено). Снятие флажков, кажется, не показывает какое-то странное поведение. Есть идеи почему?

Обновление: проверяется флажок в обратном направлении в зависимости от количества элементов на экране. Я имею в виду, что если есть 5 видимых элементов, то при нажатии на 1-й элемент проверяется 5-й, при нажатии на 2-й проверяется 4-й, при нажатии на 3-й проверяется 3-й. Кроме того, после проверки все они начинают вести себя правильно.

По-видимому, комментируя это, проблема исчезнет:

    if (holder.chkSelect != null) {
        holder.chkSelect.setOnCheckedChangeListener(this);
    }

Это определенно связано с тем, что showMultiPanel выскочит и, возможно, сократит количество видимых строк. Хотя я не понимаю, почему он работал нормально с ArrayAdapter.

Вот копия моего CursorAdapter

public class InboxAdapter extends CursorAdapter implements CheckBox.OnCheckedChangeListener {
    private int mCheckedCount = 0;

    public InboxAdapter(Context context, Cursor c) {
        super(context, c);
    }

    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if (buttonView.getId() == R.id.inbox_itemcheck) {
            if (isChecked) {
                mCheckedCount++;
            }
            else {
                mCheckedCount--;
            }
            ActivityInbox.this.showMultiPanel((mCheckedCount > 0) ? true : false);
        }
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        InboxHolder holder = (InboxHolder)view.getTag();

        if (holder.txtDate != null) {
            DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
            Date d = new Date(cursor.getInt(cursor.getColumnIndex("created_on")) * 1000L);
            holder.txtDate.setText(df.format(d));
        }
        if (holder.txtSubject != null) {
            holder.txtSubject.setText(cursor.getString(cursor.getColumnIndex("subject")));
            if (cursor.getInt(cursor.getColumnIndex("read")) == 0) {
                holder.txtSubject.setTypeface(null, Typeface.BOLD);
            }
            else {
                holder.txtSubject.setTypeface(null, Typeface.NORMAL);
            }
        }

        if(holder.txtSummary != null) {
            holder.txtSummary.setText(cursor.getString(cursor.getColumnIndex("summary")));
        }

        if (cursor.getInt(cursor.getColumnIndex("read")) == 0) {
            view.setBackgroundResource(R.drawable.selector_inbox_unread);
        }
        else {
            view.setBackgroundResource(R.drawable.selector_inbox_read);
        }

        if (holder.lMessageType != null) {
            if (cursor.getInt(cursor.getColumnIndex("read")) == 0) {
                holder.lMessageType.setVisibility(View.VISIBLE);
            }
            else {
                holder.lMessageType.setVisibility(View.INVISIBLE);
            }
        }
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        LayoutInflater inflater = LayoutInflater.from(context);
        View v = inflater.inflate(R.layout.layout_inbox_item, parent, false);

        InboxHolder holder = new InboxHolder();
        holder.txtDate = (TextView) v.findViewById(R.id.inbox_item_date);
        holder.txtSubject = (TextView) v.findViewById(R.id.inbox_item_subject);
        holder.txtSummary = (TextView) v.findViewById(R.id.inbox_item_summary);
        holder.chkSelect = (CheckBox) v.findViewById(R.id.inbox_itemcheck);
        holder.lMessageType = (LinearLayout) v.findViewById(R.id.inbox_messagetype);

        v.setTag(holder);

        if (holder.chkSelect != null) {
            holder.chkSelect.setOnCheckedChangeListener(this);
        }
        return v;
    }

}

1 Ответ

0 голосов
/ 02 сентября 2010

Обратите внимание, что ListView может повторно использовать один View для более чем одного ряда таблицы, и адаптер самостоятельно решает, произойдет ли это. Я полагаю, что CursorAdapter настроен так, чтобы делать это, где это возможно, путем объединения экземпляров представления и создания только достаточного количества для построения экрана.

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

Если вы хотите придерживаться CursorAdapter, вам нужно сохранить проверенные состояния самостоятельно. Одним из способов будет сохранение HashSet идентификаторов, которые проверены. В вашем флажке нажмите «Слушатель», обновите его, добавив или удалив идентификатор этой строки в наборе. В bindView установите состояние флажка в зависимости от того, находится ли идентификатор строки на карте. Вы можете также захотеть установить слушателя в bindView, где вы можете иметь локальную переменную final, установленную на id, и использовать это значение в коде для слушателя.

...