首页 > 解决方案 > 在 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);
    }
}

标签: androidxamarinandroid-recyclerviewandroid-viewholderandroid-radiogroup

解决方案


您可以将侦听器添加到您的RadioGroup并像这样修改您的适配器:</p>

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;
        }
    }
}

推荐阅读