Подтвердить что ты не робот

Выбор одного значения RadioButton и прокрутка назад, удаление выбранного в RecyclerView

В моем приложении отображается 20 вопросов с несколькими вариантами ответов с помощью RecyclerView.

Если я изменил значение первого RadioGroup и прокручивается вниз, снова прокручивает удаление выбранного значения в RecycelarView, а также я хочу использовать это выбранное значение RadioButton далее, я также был отмечен link1, но я не понял, что он делает.

Вот мой фрагмент кода кода, дайте мне знать, если вам нужно какое-либо разъяснение.

    package com.testing.survey;

import java.util.List;

import android.annotation.SuppressLint;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.TextView;

@SuppressWarnings("rawtypes")
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {

    private List<Student> stList;

    public DataAdapter(List<Student> students) {
        this.stList = students;
    }

    // Create new views
    @Override
    public DataAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
            int viewType) {
        // create a new view
        View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(
                R.layout.list_row, null);

        // create ViewHolder

        ViewHolder viewHolder = new ViewHolder(itemLayoutView);

        return viewHolder;
    }

    @SuppressLint("UseValueOf") @Override
    public void onBindViewHolder(ViewHolder viewHolder,int position) {

        final int pos = position;

        viewHolder.tvQuestionNumber.setText(stList.get(position).getQuestionNumber());

        viewHolder.tvQuestion.setText(stList.get(position).getQuestion());

        viewHolder.rbAns1.setText(stList.get(position).getAnswer1());

        viewHolder.rbAns2.setText(stList.get(position).getAnswer2());

        viewHolder.rbAns3.setText(stList.get(position).getAnswer3());

        viewHolder.rbAns4.setText(stList.get(position).getAnswer4());

        viewHolder.rbAns5.setText(stList.get(position).getAnswer4());

        //viewHolder.rgAnswers.clearCheck();

        viewHolder.rgAnswers.check(stList.get(position).getSelectedRadioButtonId());
        viewHolder.rgAnswers.setTag(new Integer(position));


        Log.v("select"+position,stList.get(position).getSelectedRadioButtonId()+"");

        viewHolder.rgAnswers.setOnCheckedChangeListener(new OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                // TODO Auto-generated method stub
                int radioButtonID = group.getCheckedRadioButtonId();
                View radioButton = group.findViewById(radioButtonID);
                int clickedPos = ((Integer)group.getTag()).intValue(); 

                //Student contact=(Student)group.getTag();

                //contact.setSelectedRadioButtonId(radioButtonID);
                stList.get(clickedPos).setSelectedRadioButtonId(radioButtonID);


                Log.v("hello"+clickedPos,stList.get(clickedPos).getSelectedRadioButtonId()+"");
            }
        });

    }

    // Return the size arraylist
    @Override
    public int getItemCount() {
        return stList.size();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        public TextView tvQuestionNumber;
        public TextView tvQuestion;

        public RadioGroup rgAnswers;
        public RadioButton rbAns1,rbAns2,rbAns3,rbAns4,rbAns5;

        public Student singlestudent;

        public ViewHolder(View itemLayoutView) {
            super(itemLayoutView);

            tvQuestionNumber = (TextView) itemLayoutView.findViewById(R.id.tvQuestionNumber);

            tvQuestion = (TextView) itemLayoutView.findViewById(R.id.tvQuestion);
            rgAnswers=(RadioGroup)itemLayoutView.findViewById(R.id.rgAnswers);
            rbAns1=(RadioButton)itemLayoutView.findViewById(R.id.rbAnswer1);
            rbAns2=(RadioButton)itemLayoutView.findViewById(R.id.rbAnswer2);
            rbAns3=(RadioButton)itemLayoutView.findViewById(R.id.rbAnswer3);
            rbAns4=(RadioButton)itemLayoutView.findViewById(R.id.rbAnswer4);
            rbAns5=(RadioButton)itemLayoutView.findViewById(R.id.rbAnswer5);

        }

    }

    // method to access in activity after updating selection
    public List<Student> getStudentist() {
        return stList;
    }

}
4b9b3361

Ответ 1

Я создал образец кода, который будет работать согласно вашему запросу.

Сначала мы должны создать xml следующим образом:

 <?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>

Затем мы создадим интерфейс следующим образом

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

Затем мы создадим класс модели следующим образом:

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

Затем мы создадим представление для строки:

<?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>

Класс адаптера следующим образом:

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

Затем класс Activity:

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

}
 }

Я попробовал решение с Radiogroup, но он не работал должным образом (иногда он сохранял старое значение). Затем я изменил способ выбора в моем классе модели.

sample

Ответ 2

Измените onBindViewHolder() на

public void onBindViewHolder(ViewHolder viewHolder, int position) {

        final int pos = position;

        viewHolder.tvQuestionNumber.setText(stList.get(position).getQuestionNumber() + "");

        viewHolder.tvQuestion.setText(stList.get(position).getQuestion());

        viewHolder.rbAns1.setText(stList.get(position).getAnswer1());

        viewHolder.rbAns2.setText(stList.get(position).getAnswer2());

        viewHolder.rbAns3.setText(stList.get(position).getAnswer3());

        viewHolder.rbAns4.setText(stList.get(position).getAnswer4());

        viewHolder.rbAns5.setText(stList.get(position).getAnswer5());

        //viewHolder.rgAnswers.clearCheck();

        viewHolder.rgAnswers.setTag(position);


        Log.v("select" + position, stList.get(position).getSelectedRadioButtonId() + "");

        viewHolder.rgAnswers.setOnCheckedChangeListener(new OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                // TODO Auto-generated method stub
                int radioButtonID = group.getCheckedRadioButtonId();
                View radioButton = group.findViewById(radioButtonID);
                int clickedPos = (Integer) group.getTag();


               stList.get(clickedPos).setSelectedRadioButtonId(radioButtonID);

               // if you want to get selected button info such as tag, text... etc.
                RadioButton radioButton = (RadioButton) viewHolder.itemView.findViewById(radioButtonID);

                if(radioButton != null) {
                    String customTag = radioButton.getTag().toString();
                    stList.get(clickedPos).setCustomTag(customTag);
                }


                Log.v("hello" + clickedPos, stList.get(clickedPos).getSelectedRadioButtonId() + "");
            }
        });

        viewHolder.rgAnswers.check(stList.get(position).getSelectedRadioButtonId());

    }

Он должен работать. Если какие-либо вопросы, пожалуйста, дайте мне знать.

Ответ 3

Эта проблема возникает из-за ошибки в RecyclerView или где-то в Android SDK. Во всяком случае, я принял совет от другого вопроса SO - onCheckedChanged, который был вызван автоматически.

Для RadioGroup это будет немного иначе. Есть два пути. Я рекомендую 1-й, поскольку это plug-n-play.

  • установите OnCheckedChangeListener на 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);
            }
        }
    });
    
  • или установите OnCheckedChangeListener на всех RadioButton внутри 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);
    

Ответ 4

Вы можете сделать это таким образом.....

внутри вашего класса bean добавьте одно поле:

String final_answer;
public String getFinalAnswer(){
  return final_answer;
}

public void setFinalAnswer(String final_answer){
  this.final_answer = final_answer;
}

в адаптере.....

public void onBindViewHolder(final ViewHolder viewHolder, final int position) {

    final Student student = stList.get(position);

    viewHolder.tvQuestionNumber.setText(student.getQuestionNumber());

    viewHolder.tvQuestion.setText(student.getQuestion());

    viewHolder.rbAns1.setText(student.getAnswer1());

    viewHolder.rbAns2.setText(student.getAnswer2());

    viewHolder.rbAns3.setText(student.getAnswer3());

    viewHolder.rbAns4.setText(student.getAnswer4());

    viewHolder.rbAns5.setText(student.getAnswer4());

    viewHolder.rgAnswers.clearCheck();

   if(student.getSelectedRadioButtonId()!=null)
     viewHolder.rgAnswers.check(student.getSelectedRadioButtonId());
   else
     viewHolder.rgAnswers.clearCheck();

    viewHolder.rgAnswers.setOnCheckedChangeListener(new OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(RadioGroup group, int checkedId) {
          if(checkedId != -1){
            student.setSelectedRadioButtonId(checkedId);
            RadioButton rb = (RadioButton)viewHolder.rgAnswers.
                                  findViewById(checkedId);

            student.setFinalAnswer(rb.getText);
            stList.get(position) = student;
          }
        }
    });
}

Чтобы получить выбранные ответы, наконец... напишите этот код в основном действии

  public void getSelectedAnswers(){

       for(int i=0;i<slist.length;i++){
          //get selected answer
          Log.i("answer",slist.get(i).getFinalAnswer());
       }
    }

Ответ 5

Проблема заключается в том, что представление recycler перерабатывает (например, название) ваши представления.

Система создает определенное количество ViewHolders, чтобы заполнить ваш экран после достижения этой суммы, он повторно использует уже существующие ViewHolders.

Если вы установили кнопку, отмеченную в вашем первом прослушивании, и она повторно использует ViewHolder для вашего 7-го прослушивания, кнопка все еще проверяется (потому что она установлена ​​в ViewHolder).

Чтобы устранить эту проблему, вам нужно каждый раз устанавливать внешний вид по умолчанию для ваших прихожей в onBindViewHOlder.

Update:

public void onBindViewHolder(final ViewHolder viewHolder, final int position) {

    final Student student = stList.get(position);

    viewHolder.tvQuestionNumber.setText(student.getQuestionNumber());

    viewHolder.tvQuestion.setText(student.getQuestion());

    viewHolder.rbAns1.setText(student.getAnswer1());

    viewHolder.rbAns2.setText(student.getAnswer2());

    viewHolder.rbAns3.setText(student.getAnswer3());

    viewHolder.rbAns4.setText(student.getAnswer4());

    viewHolder.rbAns5.setText(student.getAnswer4());

    viewHolder.rgAnswers.clearCheck();

    viewHolder.rgAnswers.check(student.getSelectedRadioButtonId());

    viewHolder.rgAnswers.setOnCheckedChangeListener(new OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(RadioGroup group, int checkedId) {
            student.setSelectedRadioButtonId(checkedId);
            Log.v("hello"+position,checkedId+"");
        }
    });
}

Я немного обновил ваш новый подход, возможно, это помогает?

Ответ 6

В вашем классе модели добавьте

private int checkedId = -1;

public int getCheckedId() {
    return checkedId;
}

public void setCheckedId(int checkedId) {
    this.checkedId = checkedId;
}

и измените onBindViewHolder в адаптере следующим образом:

 @Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
    viewHolder.tvQuestion.setText(stList.get(position).getQuestion());

    viewHolder.rbAns1.setText(stList.get(position).getAnswer1());
    viewHolder.rbAns2.setText(stList.get(position).getAnswer2());
    viewHolder.rbAns3.setText(stList.get(position).getAnswer3());
    viewHolder.rbAns4.setText(stList.get(position).getAnswer4());
    viewHolder.rbAns5.setText(stList.get(position).getAnswer5());

    viewHolder.radGrp.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(RadioGroup rgp, int checkedId) {
            // TODO Auto-generated method stub
            stList.get(position).setCheckedId(rgp.getCheckedRadioButtonId());
        }
    });

    viewHolder.radGrp.check(stList.get(position).getCheckedId());
}

Ответ 7

Как я видел ваш код...

просто добавьте одну строку

viewHolder.rgAnswers.setOnCheckedChangeListener(null);

в onBindViewHolder() методе выше этой строки

viewHolder.rgAnswers.check(stList.get(position).getSelectedRadioButtonId());...

, если он решит вашу проблему.. дайте мне знать... Я объясню вам сценарий, почему это происходит. Потому что я столкнулся с проблемой similer и решил с помощью этого решения.

Ответ 8

Внутри вашего студенческого класса добавляется логическая переменная isSelected. Теперь на checkedChangeListener каждой радиогруппы измените значение isSelected, чтобы отметить, было ли выбрано какое-либо значение или не было сделано никакого выбора. Теперь внутри onBindViewHolder() просто сделайте

    if(stList.get(position).isSelected){
  viewHolder.rgAnswers.check(stList.get(position).getSelectedRadioButtonId());
    }else{
    viewHolder.rgAnswers.clearCheck();
    }

В конце вы можете перебирать весь список и проверять, какие объекты, isSelected is true

Ответ 9

RecyclerView пришел через ListView и его основное свойство, которое Оно переводит ячейки во время прокрутки вверх и вниз. Из-за этого он не перемещается во время прокрутки, даже если у вас много данных в вашем списке. У вас возникает проблема из-за повторного использования ячеек в RecyclerView.

Вы можете преодолеть эту проблему, привязав данные списка RecyclerView к классу Modal с помощью метода getter и setter. Вы можете отображать checkbox отмеченные или непроверенные на основе позиции ячейки и соответствующих данных. В моем примере я использовал setOnClickListener вместо setOnCheckedChangeListenerto, чтобы показать флажок отмечен или снят флажок.