Почему мой ListView с идентификатором CheckBox запутался?

Я реализую ListView с флажком в ячейке ведьмы. Но проблема в том, что когда я проверяю одну ячейку и прокручиваю список, она путается, и другие ячейки тоже проверяются. Должен ли я делать что-то еще в моем методе getView?

Это мой CustonAdapter:

public class AcessoriosItemAdapter extends BaseAdapter {

ArrayList<AcessoriosItensLista> listAcessorios = new ArrayList<AcessoriosItensLista>();
Context context;    

public AcessoriosItemAdapter(Context context) {
    this.context = context;
}

@Override
public int getCount() {
    // TODO Auto-generated method stub
    return listAcessorios.size();
}

@Override
public Object getItem(int index) {
    // TODO Auto-generated method stub
    return listAcessorios.get(index);
}

@Override
public long getItemId(int index) {
    // TODO Auto-generated method stub
    return index;
}

@Override
public View getView(final int index, View view, ViewGroup parent) {

    if (view == null) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        view = inflater.inflate(R.layout.linha_acessorios, parent, false);             
    }       

    AcessoriosItensLista acessorios = (AcessoriosItensLista)getItem(index);

    ImageView imgAcessorio = (ImageView)view.findViewById(R.id.imgAcessorioLista);

    String nomeImagem = acessorios.getNomeImagens();
    int id = context.getResources().getIdentifier(nomeImagem, "drawable", context.getPackageName());
    imgAcessorio.setBackgroundResource(id); 

    TextView tvNome = (TextView) view.findViewById(R.id.tvNomeAcessoriosLinha);
    tvNome.setText(acessorios.getNomeAcessorio());      

    CheckBox cb = (CheckBox)view.findViewById(R.id.cbListaAcessorios);


    return view;
}   


public void addDadosAcessorios(String nomeAcessorio, String nomeImagens, boolean checked) {

    listAcessorios.add(new AcessoriosItensLista(nomeAcessorio, nomeImagens, checked));

}

}


person Roland    schedule 06.11.2013    source источник


Ответы (1)


Причина такого поведения в том, что listview повторно использует представления элементов списка. Поскольку вы не сбрасываете проверенное состояние в getView(), состояние сохраняется при прокрутке, и элементы перерабатываются.

Что необходимо, так это способ отслеживать состояние каждого флажка в зависимости от его положения. Так что можно было уверенно сказать: установлен флажок в позиции k или нет!

Вам нужно отслеживать флажки, которые были нажаты, чтобы при вызове getView() вы могли обновить состояние checkbox.

1) Поддерживать list позиций флажков, которые отмечены.

2) Если флажок установлен и установлен, добавьте его позицию в list. При повторном щелчке (снятом флажке) удалите его из списка.

3) Используйте этот list и обновите проверенное состояние флажка в getView()

Код:

public class AcessoriosItemAdapter extends BaseAdapter {

    ArrayList<AcessoriosItensLista> listAcessorios = new ArrayList<AcessoriosItensLista>(); 
    Context context;    

    // store a list of position where checbox is selected.
    ArrayList<Integer> checkedPositions = new ArrayList<Integer>();
    ...
    ...

    @Override
    public View getView(final int index, View view, ViewGroup parent) {

        if (view == null) {
            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
            view = inflater.inflate(R.layout.linha_acessorios, parent, false);             
        }       

        AcessoriosItensLista acessorios = (AcessoriosItensLista)getItem(index);

        ImageView imgAcessorio = (ImageView)view.findViewById(R.id.imgAcessorioLista);

        String nomeImagem = acessorios.getNomeImagens();
        int id = context.getResources().getIdentifier(nomeImagem, "drawable", context.getPackageName());
        imgAcessorio.setBackgroundResource(id); 

        TextView tvNome = (TextView) view.findViewById(R.id.tvNomeAcessoriosLinha);
        tvNome.setText(acessorios.getNomeAcessorio());      

        CheckBox cb = (CheckBox)view.findViewById(R.id.cbListaAcessorios);
        final Integer position = new Integer(index);

        // when checkbox is clicked, we add/remove its position to/from the list
        cb.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {

                if (((CheckBox) v).isChecked()) {
                    // if checked, we add it to the list
                    checkedPositions.add(position);
                }
                else if(checkedPositions.contains(position)) {
                    // else if remove it from the list (if it is present)
                    checkedPositions.remove(position);
                }

            }
        });
        // set the state of the checbox based on if it is checked or not.
        cb.setChecked(checkedPositions.contains(position));

        return view;
    }   

    ...
    ...
}
person Amulya Khare    schedule 06.11.2013
comment
Спасибо большое. Ты обалденный. - person Roland; 06.11.2013
comment
Привет, я знаю, что это старый вопрос, но я обнаружил проблему в принятом ответе, когда использовал его. Строка: checkedPositions.remove(position); удаляет не целое число, а позицию в списке. Это не то, что вы хотите. Вам нужно что-то вроде этого: int pos = checkedPositions.indexOf(position); checkedPositions.remove(pos); - person Tino; 04.10.2015