在 RecyclerView 中滚动时单选按钮丢失值

Radio buttons looses values when scrolling in RecyclerView

请帮我找出错误!我在这里阅读了很多关于这个问题的帖子,但我无法正常工作。对我来说,看起来我正在根据其他解决方案来做,但我遗漏了一些东西。

我使用 recyclerview 将调查作为一个问题实施,有 3 个可能的答案,其中每一行都有一个带有 3 个单选按钮的单选组。

滚动时单选按钮失去其值并且不会在 onbind 事件中再次设置。

public class MyQItem
{
    public int Id;
    public string Question;
    public int Value;

    public MyQItem(int id, string question)
    {
        Id = id;
        Question = question;
    }
}

internal class MyQFormAdapter : RecyclerView.Adapter
{
    private MyQItem[] mDataSource;

    public MyQFormAdapter(MyQItem[] mDataSource)
    {
        this.mDataSource = mDataSource;
    }

    public override int ItemCount => mDataSource.Length;

    public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
    {
        MyQViewHolder vh = holder as MyQViewHolder;

        vh.QuestionId.Text = mDataSource[position].Id.ToString();
        vh.Question.Text = mDataSource[position].Question;

        vh.Button1.CheckedChange -= Button1_CheckedChange;
        vh.Button2.CheckedChange -= Button2_CheckedChange;
        vh.Button3.CheckedChange -= Button3_CheckedChange;

        vh.Button1.Checked = mDataSource[position].Value == 1;
        vh.Button2.Checked = mDataSource[position].Value == 2;
        vh.Button3.Checked = mDataSource[position].Value == 3;

        vh.Button1.Tag = position;
        vh.Button2.Tag = position;
        vh.Button3.Tag = position;

        vh.Button1.CheckedChange += Button1_CheckedChange;
        vh.Button2.CheckedChange += Button2_CheckedChange;
        vh.Button3.CheckedChange += Button3_CheckedChange;
    }

    void Button1_CheckedChange(object sender, CompoundButton.CheckedChangeEventArgs e) => SetChecked((RadioButton)sender, 1, e.IsChecked);
    void Button2_CheckedChange(object sender, CompoundButton.CheckedChangeEventArgs e) => SetChecked((RadioButton)sender, 2, e.IsChecked);
    void Button3_CheckedChange(object sender, CompoundButton.CheckedChangeEventArgs e) => SetChecked((RadioButton)sender, 3, e.IsChecked);

    void SetChecked(RadioButton btn, int value, bool isChecked)
    {
        if (!isChecked)
            return;

        var position = (int)btn.Tag;
        mDataSource[position].Value = value;
    }

    public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
    {
        View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.MyQItemLayout, parent, false);

        MyQViewHolder vh = new MyQViewHolder(itemView);
        return vh;
    }
}

[Activity(Label = "MyQEditActivity")]
public class MyQEditActivity : Activity
{
    MyQItem[] mDataSource = new MyQItem[] { 
        new MyQItem(1, "Lorem Ipsum"),
        new MyQItem(2, "Lorem Ipsum"),
        new MyQItem(3, "Lorem Ipsum"),
        new MyQItem(4, "Lorem Ipsum"),
        new MyQItem(5, "Lorem Ipsum"),
        new MyQItem(6, "Lorem Ipsum"),
        new MyQItem(7, "Lorem Ipsum"),
        new MyQItem(8, "Lorem Ipsum"),
        new MyQItem(9, "Lorem Ipsum"),
        new MyQItem(10, "Lorem Ipsum"),
        new MyQItem(11, "Lorem Ipsum"),
        new MyQItem(12, "Lorem Ipsum"),
    };

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        SetContentView(Resource.Layout.MyQEditLayout);

        var recyclerView = FindViewById<RecyclerView>(Resource.Id.recyclerView);
        recyclerView.SetLayoutManager(new LinearLayoutManager(this));
        recyclerView.SetAdapter(new MyQFormAdapter(mDataSource));
    }

}

public class MyQViewHolder : RecyclerView.ViewHolder
{
    public TextView QuestionId { get; private set; }
    public TextView Question { get; private set; }
    public RadioButton Button1 { get; private set; }
    public RadioButton Button2 { get; private set; }
    public RadioButton Button3 { get; private set; }

    public MyQViewHolder(View itemView) : base(itemView)
    {
        QuestionId = itemView.FindViewById<TextView>(Resource.Id.MyQuestionId);
        Question = itemView.FindViewById<TextView>(Resource.Id.MyQuestion);

        Button1 = itemView.FindViewById<RadioButton>(Resource.Id.noButton);
        Button2 = itemView.FindViewById<RadioButton>(Resource.Id.someButton);
        Button3 = itemView.FindViewById<RadioButton>(Resource.Id.yesButton);
    }
}

您可以将监听器添加到您的 RadioGroup 并像这样修改您的适配器:

class MyQFormAdapter : RecyclerView.Adapter, RadioGroup.IOnCheckedChangeListener
{
    private MyQItem[] mDataSource;
    public MyQFormAdapter(MyQItem[] mDataSource)
     {
      this.mDataSource = mDataSource;
     }


    public override int ItemCount => mDataSource.Length;

    public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
    {
        MyQViewHolder vh = holder as MyQViewHolder;

       // cancel the listener to prevent RadioGroup from displaying confusing key codes
        vh.Group.SetOnCheckedChangeListener(null);
        vh.Group.ClearCheck();
        vh.Group.Tag = position;

        switch (mDataSource[position].Value)
        {
            case 1:
                vh.Group.Check(Resource.Id.noButton);
                break;
            case 2:
                vh.Group.Check(Resource.Id.someButton);
                break;
            case 3:
                vh.Group.Check(Resource.Id.yesButton);
                break;

        }
        vh.QuestionId.Text = mDataSource[position].Id.ToString();
        vh.Question.Text = mDataSource[position].Question;
        vh.Group.SetOnCheckedChangeListener(this);
    }
    public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
    {

        View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.MyQItemLayout, parent,false);

        MyQViewHolder vh = new MyQViewHolder(itemView);
        return vh;
    }

    public class MyQViewHolder : RecyclerView.ViewHolder
    {
        public TextView QuestionId { get; private set; }
        public TextView Question { get; private set; }

        public RadioGroup Group { get; private set; }
        public MyQViewHolder(View itemView) : base(itemView)
        {
            QuestionId = itemView.FindViewById<TextView>(Resource.Id.MyQuestionId);
            Question = itemView.FindViewById<TextView>(Resource.Id.MyQuestion);
            Group = itemView.FindViewById<RadioGroup>(Resource.Id.radiogroup);
        }
    }

    public void OnCheckedChanged(RadioGroup @group, int checkedId)
    {
        switch (checkedId)
        {
            case Resource.Id.noButton:
                mDataSource[(int) @group.Tag].Value = 1;
                break;
            case Resource.Id.someButton:
                mDataSource[(int)@group.Tag].Value = 2;
                break;
            case Resource.Id.yesButton:
                mDataSource[(int)@group.Tag].Value = 3;
                break;
        }
    }
}