为啥当我在选中 CheckBox 的情况下滚动 ListView 时,它会变为未选中状态?

Posted

技术标签:

【中文标题】为啥当我在选中 CheckBox 的情况下滚动 ListView 时,它会变为未选中状态?【英文标题】:Why When I scroll my ListView with CheckBox selected it becomes unselected?为什么当我在选中 CheckBox 的情况下滚动 ListView 时,它会变为未选中状态? 【发布时间】:2015-08-20 21:43:35 【问题描述】:

我在这里看到一些帖子谈论这个,但我没有看到任何解决我的问题的答案。

我有这个带有一些 TextView 和一个 CheckBox 的 ListView,一切都很好,除了当我滚动列表时,一些选中的变为未选中。

这是我的 getView 适配器代码:

public View getView(int position, View convertView, ViewGroup parent) 
    Agendamento item = getItem(position);

    ViewHolder viewHolder;
    if (convertView == null) 
        viewHolder = new ViewHolder();
        LayoutInflater inflater = LayoutInflater.from(getContext());
        convertView = inflater.inflate(R.layout.item_lista_agendamento, parent, false);

        viewHolder.campoNomeCliente = (TextView) convertView.findViewById(R.id.campoNomeCliente);
        viewHolder.campoNomePaciente = (TextView) convertView.findViewById(R.id.nomePaciente);
        viewHolder.campoNomeMedico = (TextView) convertView.findViewById(R.id.campoNomeMedico);
        viewHolder.campoCorStatus = (TextView) convertView.findViewById(R.id.campoCorStatus);
        viewHolder.campoCorStatus = (TextView) convertView.findViewById(R.id.campoCorStatus);
        viewHolder.campoDataHoraInc = (TextView) convertView.findViewById(R.id.campoDataHoraInc);

        CheckBox chk = (CheckBox) convertView.findViewById(R.id.marcado);

        viewHolder.chkMarcado = chk;
        viewHolder.chkMarcado.setTag(position);
        convertView.setTag(viewHolder);
     else 
        viewHolder = (ViewHolder) convertView.getTag();
    

    String codigoMedico = item.getCodigoMedico();
    String codigoCliente = item.getCodigoCliente();

    Medico medico = rep.getMedicoPorCodigo(codigoMedico);
    Cliente cliente = rep.getClientePorCodigo(codigoCliente);

    String status = item.getStatus().trim();
    int backgroundColor = 0;
    if (status.equals("S")) 
        backgroundColor = R.color.corSeparada;
    
    if (status.equals("F")) 
        backgroundColor = R.color.corFinalizada;
    
    if (status.equals("E")) 
        backgroundColor = R.color.corEncerrada;
    
    if (status.equals("N")) 
        backgroundColor = R.color.corNova;
    

    String dataInc = item.getDataInclusao().replaceAll("[/]", "");
    String dataBr = "";
    if (!dataInc.trim().equals("")) 
        String dia = dataInc.substring(4, 6);
        String mes = dataInc.substring(6, 8);
        String ano = dataInc.substring(0, 4);
        dataBr = dia + "/" + mes + "/" + ano;
    
    String horaInc = item.getHoraInclusao().trim();
    dataBr += " " + horaInc;

    viewHolder.campoCorStatus.setBackgroundResource(backgroundColor);
    viewHolder.campoNomeCliente.setText(cliente == null ? "(cliente)" : cliente.getNome());
    viewHolder.campoNomePaciente.setText(item.getNomePaciente());
    viewHolder.campoNomeMedico.setText(medico == null ? "(médico)" : medico.getNome());
    viewHolder.campoDataHoraInc.setText(dataBr + " (" + item.getId() + ")");

    final Agendamento item1 = item;
    viewHolder.chkMarcado.setOnCheckedChangeListener(null);
    viewHolder.chkMarcado.setChecked(item.isSelected());
    viewHolder.chkMarcado.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() 

        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) 
            if(isChecked)
                selectedList.add(item1);
             else 
                selectedList.remove(item1);
            
        
    );

    if (position % 2 == 0) 
        convertView.setBackgroundResource(R.drawable.cor_zebra2);
     else 
        convertView.setBackgroundResource(R.drawable.cor_zebra1);
    

    // Return the completed view to render on screen
    return convertView;

这是向上滚动之前的结果,向上滚动之后那些选中的复选框变为未选中:

【问题讨论】:

因为您在创建 OnCheckedChangedListener 时设置了它,并且每次为该视图调用 getView 时都会触发它,因为 ListView 正在重用您提供的视图。如果您想避免这种情况,请将 View 的 OnCheckChangedListener 设置为 null,然后再将其设置为选中或未选中,然后设置值,然后将 OnCheckedChangeListener 设置回您的侦听器。这需要在 if(convertView == null) 检查之外完成 ListView 保存当前显示的实例。当您滚动 ListView 时,您将获得第一个可见项目的索引和可见项目的数量。当用户滚动列表视图时,您必须使用此信息手动实现选择功能 我刚刚做了你所说的 Guardanis 但得到了相同的结果,请看我的编辑 【参考方案1】:

ListView 的工作方式是回收使用不同数据填充的相同视图。因此,需要视图持有者模式,看起来您正在使用它。

因此,为了让您的列表正常工作,您需要将选中状态保存到您的支持数据模型中。看起来您可能已经在模型中有一个“选定的”布尔值?如果是这样,您只需将状态保存到此布尔值即可。

viewHolder.chkMarcado.setChecked(item.isSelected());
viewHolder.chkMarcado.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() 
    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) 
        item.setSelected(isChecked);
    
);

【讨论】:

非常感谢我的朋友,你的建议就像一个魅力!

以上是关于为啥当我在选中 CheckBox 的情况下滚动 ListView 时,它会变为未选中状态?的主要内容,如果未能解决你的问题,请参考以下文章

listView中带有复选框的自定义布局:当我删除一行时,如果选中它(checkBox = true),则下一行将获得检查

delphi:dbgrideh中设置了checkbox列,不能勾选

Excel 控件中的checkbox 如何被选中? 为啥不是像"窗体"中的复选框一样,拉出来,直接用鼠标单击就能选中了

Android入门第28天-ListView嵌套CheckBox在滚动时失去选中状态的问题

为啥 checkbox.IsChecked() 不返回选中状态

如何获取listview里选中的checkbox