Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have a custom ListView with some TextViews, EditTexts and a checkbox that represents a item of a shopping list. When I type values in the value EditText, I check the checkbox and a Toast show me the sum of the values multiplied by their respective quantities and when all checkboxes of all items are checked a dialog show me the total value of the shopping list. My problem is that when the numeric keyboard is hidden after I enter values the checkboxes lost their checked states. What could be the problem?

This is some part of the code of my getView method:

@Override
public View getView(final int position, View convertView, ViewGroup parent) {

    final ViewHolder holder;

    SharedPreferences sharedPrefs = contexto.getSharedPreferences("sharedPrefs", Context.MODE_PRIVATE);

    if (convertView == null) {
        LayoutInflater inflater = contexto.getLayoutInflater();
        convertView = inflater.inflate(R.layout.items_layout, null);
        holder = new ViewHolder();
        holder.texto = (TextView) convertView.findViewById(R.id.txtDescricao);
        holder.checkbox = (CheckBox) convertView.findViewById(R.id.chkProduto);
        holder.edtValor = (EditText) convertView.findViewById(R.id.txtValor);
        holder.edtQtde = (EditText) convertView.findViewById(R.id.txtQuantidade);
        holder.btnMenos = (Button) convertView.findViewById(R.id.btnMenos);
        holder.btnMais = (Button) convertView.findViewById(R.id.btnMais);
        //holder.btnExcluir = (ImageButton) convertView.findViewById(R.id.btnExcluir);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    editor = sharedPrefs.edit();

    holder.posicao = position;
    holder.texto.setText(getItem(position).getTexto());     

    if(getItem(position).getValor() > 0)
        holder.edtValor.setText(Double.toString(getItem(position).getValor()));
    else
        holder.edtValor.setText("");

    holder.edtValor.setTag(new LinhaItemTag(getItem(position), position));  
    holder.edtValor.addTextChangedListener(new TextWatcherValor(holder));       

    if(quantidades[position] > 0)
        holder.edtQtde.setText(Integer.toString(quantidades[position]));
    else
        holder.edtQtde.setText("");

    holder.edtQtde.setTag(new LinhaItemTag(getItem(position), position));   
    holder.edtQtde.addTextChangedListener(new TextWatcherQuantidade(holder));

    holder.btnMenos.setTag(new LinhaItemTag(getItem(position), position));  
    holder.btnMais.setTag(new LinhaItemTag(getItem(position), position));
    //holder.btnExcluir.setTag(new LinhaItemTag(getItem(position), position));


    holder.checkbox.setOnCheckedChangeListener(null);
    //holder.checkbox.setChecked(getItem(position).Selecionado());
    getItem(position).setSelecionado(sharedPrefs.getBoolean("CheckValue"+position, false));
    holder.checkbox.setChecked(getItem(position).Selecionado());
    holder.checkbox.setTag(new LinhaItemTag(getItem(position), position));

    holder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            LinhaItemTag elemento = (LinhaItemTag) buttonView.getTag();
            elemento.item.setSelecionado(isChecked);        
            editor.putBoolean("CheckValue"+position, isChecked);
            editor.commit();

            if (isChecked) {
                pegos[elemento.position] = true;                    
            } else {
                pegos[elemento.position] = false;               
            }

            String vlrTotal = calculaTotal();

            boolean checados = true;
            for (int i = 0; i < lista.size(); i++) {
                if (!pegos[i]) {
                    checados = false;
                    break;
                }
            }           
            if (checados) {             
                mostraDlgFinaliza();                                        
            }
            else if(getItem(elemento.position).Selecionado())
            {
                Toast.makeText(contexto, "R$ " + vlrTotal, Toast.LENGTH_LONG).show();
            }
        }
    });

//Other piece of code

return convertView;

}
share|improve this question

1 Answer

up vote 1 down vote accepted

Use setOnClickListener() Instead of setOnCheckChangedListener for Android CheckBoxes

Instead of setOnCheckChangedListener(), you should use setOnClickListener() and determine the checked setting via holder.checkbox.isChecked().

Example:

holder.checkBox.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View arg0) {
        final boolean isChecked = holder.checkBox.isChecked();
        // Do something here.
    }
});

The CheckBox changed listener is not valid because the individual CheckBox objects are constantly being recycled and reset for various reasons such as ListView/GridView scroll or screen redraw due to orientation/keyboard change. Each CheckBox can show up in various positions as they go in and out of view. That is why you must set the check value every time in getView() and you must respond to clicks.

Otherwise, if you respond only to checked changes, you will receive checkChanged callbacks at unexpected times as the CheckBox are recycled and sometimes you will not receive the callback at all if the checked states in cells being swapped have the same check setting.

share|improve this answer
Thank you David! – Danilo Silva Apr 13 at 19:35

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.