带有复选框的CustomListview自动检查/取消选中项目

时间:2017-04-04 15:27:56

标签: android xamarin

我使用自定义列表视图和复选框。当我向下滚动列表视图时,我会看到一些自动选中的复选框。当我向上滚动时,某些已选中的用户已取消选中。

class MyListViewAdapterExtras :BaseAdapter<ExtrasPreviewClass>
{
public List<ExtrasPreviewClass> mitems;
private Context mContext;
public MyListViewAdapterExtras(Context context, List<ExtrasPreviewClass> items)
{
mitems = items;
mContext = context;

}
public override int Count
{
    get
    {
        return mitems.Count;
    }
}
public override long GetItemId(int position)
{
    return position;
}
public override ExtrasPreviewClass this[int position]
{
    get
    {
        return mitems[position];
    }

}

public override View GetView(int position, View convertView, ViewGroup parent)
{


        View row = convertView;
        if (row == null)
        {
            row = LayoutInflater.From(mContext).Inflate(Resource.Layout.ExtrasPreview, null, false);

        }

        TextView txtName = row.FindViewById<TextView>(Resource.Id.txtName);
        txtName .Text = mitems[position].Name;
        CheckBox txtCheckBox= row.FindViewById<CheckBox>(Resource.Id.txtCheckBox);
    txtCheckBox.Text = Convert.ToString(mitems[position].CheckBox);

        return row;
    }

有什么方法可以解决这个问题吗?

2 个答案:

答案 0 :(得分:0)

GetView()方法中,如果convertView不是null,那么您将重用View。该视图将具有来自其分配的任何位置的数据。如果您不更改数据,它将显示在不同的广告位中并导致您看到的内容。

要解决此问题,您需要确保GetView()View的所有数据设置为指定位置的正确值,无论View是否重复使用

以下是我认为relevant example的链接。我已经提取了getView()代码并发表了评论。我希望这会有所帮助。

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // Modified to reuse convertView
    if (convertView == null) {
        LayoutInflater inflater = ((Activity) context).getLayoutInflater();
        convertView = inflater.inflate(R.layout.row, parent, false);
    }
    TextView name = (TextView) convertView.findViewById(R.id.textView1);

    // Find the checkBox view
    CheckBox cb = (CheckBox) convertView.findViewById(R.id.checkBox1);
    name.setText(modelItems[position].getName());

    // Set the checkBox as "checked" or "unchecked" depending upon our internal
    // data structure. Here it is "modelItems[]". If we don't do this, then the checkBox
    // will be set to whatever it was set to if convertView is reused.
    if (modelItems[position].getValue() == 1)
        cb.setChecked(true);
    else
        cb.setChecked(false);
    return convertView;
}

答案 1 :(得分:0)

  

我使用自定义列表视图和复选框。当我向下滚动列表视图时,我会看到一些自动选中的复选框。当我向上滚动时,某些已选中的用户已取消选中。

正如@Cheticamp所说,ListView中的视图将在滚动期间重复使用,您需要每次getView调用时更新视图。

从您的代码中,您已经有了文字,但没有更新ischecked州。为实现这一目标,我们需要遵循以下步骤:

  1. 更新Model类(ExtrasPreviewClass)以添加bool字段以存储isChecked状态:

    public class ExtrasPreviewClass
    {
        public ExtrasPreviewClass(string name, string checkbox)
        {
            this.Name = name;
            this.CheckBox = checkbox;
            this.IsChecked = false;
        }
        public String Name { get; set; }
    
        public String CheckBox { get; set; }
    
        public bool IsChecked { get; set; }
    }
    
  2. 更新适配器中的GetView方法,并在GetView下面添加一个事件监听器类:

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        View row = convertView;
        if (row == null)
        {
            row = LayoutInflater.From(mContext).Inflate(Resource.Layout.ItemView, null, false);
        }
    
        TextView txtName = row.FindViewById<TextView>(Resource.Id.txtName);
    
        txtName.Text = mitems[position].Name;
        CheckBox txtCheckBox = row.FindViewById<CheckBox>(Resource.Id.txtCheckBox);
        txtCheckBox.Text = Convert.ToString(mitems[position].CheckBox);
    
        //SetOnCheckedChangeListener must be set before txtCheckBox.Checked = mitems[position].IsChecked
        txtCheckBox.SetOnCheckedChangeListener(new CheckChangeListener(position, ref mitems));
        txtCheckBox.Checked = mitems[position].IsChecked;
        Console.WriteLine("Set the CheckBox " + position + " to "+ mitems[position].IsChecked);
    
        return row;
    }
    
    public class CheckChangeListener : Java.Lang.Object, CompoundButton.IOnCheckedChangeListener
    {
        int position;
        List<ExtrasPreviewClass> items;
        public CheckChangeListener(int position,ref List<ExtrasPreviewClass> items)
        {
            this.position = position;
            this.items = items;
        }
        public void OnCheckedChanged(CompoundButton buttonView, bool isChecked)
        {
            items[position].IsChecked = isChecked;
            Console.WriteLine("Set the " + position + " IsChecked to " + isChecked);
        }
    }
    
  3. 注意:txtCheckBox.SetOnCheckedChangeListener之前应调用txtCheckBox.Checked = mitems[position].IsChecked。否则,你会得到意想不到的行为。

    更新:可以更新ChangeCheckListener旁边的视图,你需要像下面那样修改监听器:

    public class CheckChangeListener2 : Java.Lang.Object, CompoundButton.IOnCheckedChangeListener
    {
        int position;
        List<ExtrasPreviewClass> items;
        View row;
        public CheckChangeListener2(int position, ref List<ExtrasPreviewClass> items,View row)
        {
            this.position = position;
            this.items = items;
            this.row = row;
        }
        public void OnCheckedChanged(CompoundButton buttonView, bool isChecked)
        {
            items[position].IsChecked = isChecked;
            TextView txtName = row.FindViewById<TextView>(Resource.Id.txtName);
            //update the name
            txtName.Text = items[position].Name;
            Console.WriteLine("Set the " + position + " IsChecked to " + isChecked);
        }
    }