Selecting one RadioButton value and scrolling back removing the selected one in RecyclerView

后端 未结 9 1885
温柔的废话
温柔的废话 2020-12-15 18:24

In my application am displaying 20 multiple choice questions with the help of RecyclerView.

If I change the value of first RadioGroup and s

相关标签:
9条回答
  • 2020-12-15 19:02

    This problem occurs because of a bug in either RecyclerView or somewhere in the Android SDK. Anyway, I took the advice from another SO question - onCheckedChanged called automatically.

    For RadioGroup, it will be a little different. There are two ways to go about. I recommend 1st one since it is plug-n-play.

    1. set OnCheckedChangeListener on RadioGroup:

      mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
          @Override
          public void onCheckedChanged(RadioGroup group, int checkedId) {
              if(checkedId == -1) {
                  Log.v("onCheck", "Android bug since RadioButton doesn't get unchecked normally!");
              }
              else {
                  Log.v("onCheck", "Valid click. By user");
                  mMyListObjectArr[position].setChecked(checkedId);
              }
          }
      });
      
    2. or set onCheckedChangeListener on all RadioButtons inside the RadioGroup:

      CompoundButton.OnCheckedChangeListener onCheckedChangeListener = new CompoundButton.OnCheckedChangeListener() {
          @Override
          public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
              if(buttonView.isPressed()) {
                  Log.v("onCheck", position + ", valid click by user");
                  mMyListObjectArr[position].setChecked(buttonView.getId());
              }
              else {
                  Log.v("onCheck", "Android bug");
              }
          }
      };
      mRadioButton1.setOnCheckedChangeListener(onCheckedChangeListener);
      mRadioButton2.setOnCheckedChangeListener(onCheckedChangeListener);
      
    0 讨论(0)
  • 2020-12-15 19:07

    RecyclerView came over ListView and its major property that is It Reuses cells while scrolling up and down. Due to this it do not flick while scrolling even if you have lots of data in your list. You are getting problem due to Reuse of cells in RecyclerView.

    You can overcome to this problem by binding your RecyclerView list data to Modal class with getter and setter method. You can display checkbox checked or unchecked on basis of cell position and corresponding data. In my sample i used setOnClickListener instead of setOnCheckedChangeListenerto to show checkbox checked or unchecked.

    0 讨论(0)
  • 2020-12-15 19:12

    I created a sample code that will work as per your req.

    First we have to create the xml as follows :

     <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerViewAppList"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
    </LinearLayout>
    

    Then we will create an interface as follows

    public interface OnOptionSelected {
    public void onOptionSelected(int position,int itemSelected);
    }
    

    Then we will create the model class as follows :

    public class QuestionModel {
    
    private String question;
    private int seleectedAnswerPosition;
    private boolean op1Sel,op2Sel,op3Sel; // options 
    
    public boolean isOp1Sel() {
        return op1Sel;
       }
    
    public void setOp1Sel(boolean op1Sel) {
        this.op1Sel = op1Sel;
        if(op1Sel){ // To make sure only one option is selected at a time
            setOp2Sel(false);
            setOp3Sel(false);
        }
       }
    
        public boolean isOp2Sel() {
          return op2Sel;
       }
    
       public void setOp2Sel(boolean op2Sel) {
        this.op2Sel = op2Sel;
        if(op2Sel){
            setOp1Sel(false);
            setOp3Sel(false);
         }
          }
    
     public boolean isOp3Sel() {
        return op3Sel;
         }
    
     public void setOp3Sel(boolean op3Sel) {
        this.op3Sel = op3Sel;
        if(op3Sel){
            setOp2Sel(false);
            setOp1Sel(false);
         }
        }
    
        public int getSeleectedAnswerPosition() {
        return seleectedAnswerPosition;
        }
    
      public void setSeleectedAnswerPosition(int seleectedAnswerPosition) {
        this.seleectedAnswerPosition = seleectedAnswerPosition;
       }
    
      public String getQuestion() {
        return question;
      }
     public void setQuestion(String question) {
        this.question = question;
      }
         } 
    

    Then we will create the view for row :

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
    android:id="@+id/question"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
    
        <RadioButton
            android:id="@+id/radoptionOne"
            android:text="May Be"
            android:checked="false"
            android:saveEnabled="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <RadioButton
            android:checked="false"
            android:id="@+id/radoptionTwo"
            android:text="NO"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <RadioButton
            android:checked="false"
            android:id="@+id/radoptionThree"
            android:text="Yes"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
       </LinearLayout>
    

    Adapter class as follows:

     public class QuestionAdapter extends      RecyclerView.Adapter<QuestionAdapter.ViewHolder> {
    
       private List<QuestionModel> questionModels;
    
    
    public void setOnOptionSelected(OnOptionSelected onOptionSelected) {
        this.onOptionSelected = onOptionSelected;
    }
    
    private OnOptionSelected onOptionSelected;
    
    
    public List<QuestionModel> getQuestionModels() {
        return questionModels;
    }
    
    public void setQuestionModels(List<QuestionModel> questionModels) {
        this.questionModels = questionModels;
    }
    
    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        TextView question;
        RadioGroup radioGroup;
        RadioButton op1, op2, op3;
    
        ViewHolder(View view) {
            super(view);
            question = (TextView) view.findViewById(R.id.question);
            //radioGroup=(RadioGroup)view.findViewById(R.id.radGroup);
            op1 = (RadioButton) view.findViewById(R.id.radoptionOne);
            op2 = (RadioButton) view.findViewById(R.id.radoptionTwo);
            op3 = (RadioButton) view.findViewById(R.id.radoptionThree);
            op1.setOnClickListener(this);
            op2.setOnClickListener(this);
            op3.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.radoptionOne:
                    onOptionSelected.onOptionSelected(getAdapterPosition(), 1);
                    break;
    
                case R.id.radoptionTwo:
                    onOptionSelected.onOptionSelected(getAdapterPosition(), 2);
                    break;
    
                case R.id.radoptionThree:
                    onOptionSelected.onOptionSelected(getAdapterPosition(), 3);
                    break;
            }
        }
    }
    
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v;
        // create a normal view
        v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.row_view, parent, false);
        return new ViewHolder(v);
    
    }
    
    @Override
    public void onBindViewHolder(ViewHolder viewHolder, final int position) {
        viewHolder.question.setText(questionModels.get(position).getQuestion());
    
        Log.e("POSITION" + position, "1" + questionModels.get(position).isOp1Sel());
    
        Log.e("POSITION" + position, "2" + questionModels.get(position).isOp2Sel());
        Log.e("POSITION" + position, "3" + questionModels.get(position).isOp3Sel());
    
    
        viewHolder.op1.setChecked(questionModels.get(position).isOp1Sel());
        viewHolder.op2.setChecked(questionModels.get(position).isOp2Sel());
        viewHolder.op3.setChecked(questionModels.get(position).isOp3Sel());
    
    
    }
    
    @Override
    public int getItemCount() {
        if (questionModels != null) {
            return questionModels.size();
        }
        return 0;
    }
    }
    

    Then the Activity class :

    public class MainActivity extends Activity implements OnOptionSelected{
    
    private RecyclerView mRecyclerView;
    private List<QuestionModel> questionModels;
    private  QuestionAdapter questionAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRecyclerView =(RecyclerView)findViewById(R.id.recyclerViewAppList);
        mRecyclerView.setHasFixedSize(true);
        questionModels=new ArrayList<QuestionModel>();
        for (int i=0;i<20;i++)
        {
            QuestionModel questionModel=new QuestionModel();
            questionModel.setQuestion("Question " + (i + 1));
            questionModels.add(questionModel);
        }
        questionAdapter =new QuestionAdapter();
        questionAdapter.setOnOptionSelected(this);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        questionAdapter.setQuestionModels(questionModels);
        mRecyclerView.setLayoutManager(layoutManager);
        mRecyclerView.setAdapter(questionAdapter);
    }
    
    
    @Override
    public void onOptionSelected(int position, int itemSelected) {
        questionModels.get(position).setSeleectedAnswerPosition(itemSelected);
        switch (itemSelected){
            case 1:
                questionModels.get(position).setOp1Sel(true);
                break;
    
            case 2:
                questionModels.get(position).setOp2Sel(true);
                break;
            case 3:
                ((QuestionModel)questionModels.get(position)).setOp3Sel(true);
                break;
        }
        questionAdapter.setQuestionModels(questionModels);
        questionAdapter.notifyDataSetChanged();
       // mRecyclerView.setAdapter(questionAdapter);
    
    }
     }
    

    I tried the solution with Radiogroup but it was not working properly( sometime it was retaining the old value). Then I changed the way of the selecting options in my model class.

    0 讨论(0)
提交回复
热议问题