【问题标题】:ListView Viewholder checkbox stateListView Viewholder 复选框状态
【发布时间】:2013-04-27 08:53:45
【问题描述】:

我的 ListView 自定义适配器(及其新实现的 viewHolder)存在一些问题。我有一个 ListView,每个项目都有一个复选框(这里没有新内容)。问题是,如果我的列表中有超过 9 个项目,当我选中第一个复选框时,第十个将被自动选中(第二个与第十一个相同)就像两个项目都有一个侦听器(我相信在某种程度上是这样)。

我在这里阅读了有关 listView 的位置问题、视图回收和 ViewHolder 解决方法:How can I make my ArrayAdapter follow the ViewHolder pattern?

但我可能做错了什么,因为它不起作用......

public class PresenceListAdapter extends SimpleAdapter {
private LayoutInflater  inflater;
private List<Integer> ids;
private List<String> statuts;

public PresenceListAdapter (Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to, List<Integer> ids, List<String> statuts)
{
    super (context, data, resource, from, to);
    inflater = LayoutInflater.from (context);
    this.ids = ids;
    this.statuts= statuts;

}

@Override
public Object getItem (int position)
{
    return super.getItem (position);
}

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

    ViewHolder holder;

    if (convertView == null)
    {
        convertView = inflater.inflate (R.layout.list_text_checkbox, null);

        holder = new ViewHolder();

        holder.btn = (Button) convertView.findViewById(R.id.btnRetard);
        holder.check = (CheckBox) convertView.findViewById(R.id.checkPresent);

        if (statuts.get(position).equals("P")) {
            Drawable img = inflater.getContext().getResources().getDrawable(android.R.drawable.presence_online);
            holder.btn.setCompoundDrawablesWithIntrinsicBounds( img, null, null, null );
            holder.btn.setEnabled(true);
            holder.check.setChecked(true);
        }
        else if(statuts.get(position).equals("R"))
        {
            Drawable img = inflater.getContext().getResources().getDrawable(android.R.drawable.presence_away);
            holder.btn.setCompoundDrawablesWithIntrinsicBounds( img, null, null, null );
            holder.btn.setEnabled(true);
            holder.check.setChecked(true);
        }
        else 
        {
            Drawable img = inflater.getContext().getResources().getDrawable(android.R.drawable.presence_invisible);
            holder.btn.setCompoundDrawablesWithIntrinsicBounds( img, null, null, null );
            holder.check.setChecked(false);
        }

        convertView.setTag(holder);
    }
    else 
    {
        holder = (ViewHolder) convertView.getTag();
    }

    int id = ids.get(position);

    if(id != 0)
    {
        holder.check.setTag(id);
        holder.btn.setTag(id);
    }

    return super.getView (position, convertView, parent);
}

static class ViewHolder {
    Button btn;
    CheckBox check;
}

还有我的听众: public void changerPresent(View v) {

    CheckBox checkPresent = (CheckBox) v;
    int idPersonne = (Integer) checkPresent.getTag();
    View parent = (View)v.getParent();
    Button btn = (Button) parent.findViewById(R.id.btnRetard);

    if(checkPresent.isChecked()) {
        gestion.updatePresence(idPersonne, idSeance, "P");

        btn.setEnabled(true);
        setBtnRetardPresent(btn);           
    }
    else 
    {
        gestion.updatePresence(idPersonne, idSeance, "A");
        btn.setEnabled(false);
        setBtnRetardAbsent(btn);

    }

}

在这一点上我将不胜感激,我已经为此工作了几个小时。

非常感谢。

【问题讨论】:

    标签: java android listview checkbox adapter


    【解决方案1】:

    我是这样工作的:

    首先,您需要一个单独的数组用于检查状态。它必须与适配器的getCount() 大小相同。

    然后在您的 getView 上,您的复选框的 setOnCheckedChangedListener 必须在您的 checkbox.setChecked 语句之前。

    示例:

    holder.checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
      @Override
      public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        isChecked[position] = isChecked;
      }
    });
    
    holder.checkBox.setChecked(isChecked[position]);
    

    【讨论】:

    • 完美!感谢您的解释。
    • 有趣,你能告诉我为什么 checkchangelistener 必须在 setChecked 之前吗?谢谢
    • 如果你在onCheckChanged中还有其他的事情要做(比如更新列表项颜色等),在设置监听器之前调用setChecked就不会发生这些事情了。
    • 好的,我想我明白了,setCheckChanged 在被回收时在getView 方法中调用(getView 机制)。不是预期的方式。
    • 这样的答案,让生活变得轻松:)
    【解决方案2】:

    您应该在 ViewHolder 的初始化之外设置 CheckedBox 状态,如以下代码:

    if (convertView == null) {
        viewHolder = new ViewHolder();
        convertView.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) convertView.getTag();
    }
    
    viewHolder.checkedBox.setChecked();
    

    顺便说一句:使用 SparseBooleanArray 而不是两个列表来存储 CheckedBox 状态。

    【讨论】:

      【解决方案3】:

      问题在于 listview 回收它的视图

      所以在getView() 方法中

           if (convertView == null)
              {
          ........
               }
          else 
              {
                  holder = (ViewHolder) convertView.getTag();
      
      
              }
        // Uncheck needed boxes here... You need to implement your logic 
              if( 'position' is checked earlier)
               holder.check.setChecked(true);
              else
              holder.check.setChecked(false);
      

      如果转换不为空,您需要编写代码来管理视图的状态,因为它是一个已使用的视图,可能已选中复选框。

      【讨论】:

        猜你喜欢
        • 2015-09-28
        • 1970-01-01
        • 1970-01-01
        • 2013-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-21
        相关资源
        最近更新 更多