android - seleccionar - Seleccionando un valor de RadioButton y retrocediendo eliminando el valor seleccionado en RecyclerView
recyclerview seleccionar item (9)
Como he visto tu código ...
solo agrega una línea
viewHolder.rgAnswers.setOnCheckedChangeListener(null);
en el método onBindViewHolder()
arriba de esta línea
viewHolder.rgAnswers.check(stList.get(position).getSelectedRadioButtonId());
...
si resolvió su problema ... hágame saber ... le explicaré un escenario por qué está sucediendo ... Porque enfrenté un problema de similer y lo resolví usando esta solución.
En mi solicitud, muestro 20 preguntas de opción múltiple con la ayuda de RecyclerView
.
Si cambio el valor del primer grupo de RadioGroup
y me RadioGroup
hacia abajo, de nuevo se desplaza hacia arriba eliminando el valor seleccionado en RecycelarView
y también quiero usar más el valor de RadioButton
seleccionado, también se verificó el link1 pero no entendí lo que está haciendo.
Aquí está mi fragmento de código de muestra, hágamelo saber si necesita alguna aclaración.
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;
}
}
Creé un código de muestra que funcionará según sus requisitos.
Primero tenemos que crear el xml de la siguiente manera:
<?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>
Luego crearemos una interfaz de la siguiente manera
public interface OnOptionSelected {
public void onOptionSelected(int position,int itemSelected);
}
Luego crearemos la clase modelo de la siguiente manera:
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;
}
}
Luego crearemos la vista para la fila:
<?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>
Clase de adaptador de la siguiente manera:
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;
}
}
Luego la clase de actividad:
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);
}
}
Probé la solución con Radiogroup pero no estaba funcionando correctamente (en algún momento fue reteniendo el valor anterior). Luego cambié la forma de las opciones de selección en mi clase de modelo.
Dentro de su clase de estudiante agregue una variable booleanaSeleccionado. Ahora, en checkChangeListener de cada grupo de radiología, cambie el valor de isSelected para marcar si se ha seleccionado algún valor o no se ha realizado ninguna selección. Ahora dentro de onBindViewHolder () solo haz
if(stList.get(position).isSelected){
viewHolder.rgAnswers.check(stList.get(position).getSelectedRadioButtonId());
}else{
viewHolder.rgAnswers.clearCheck();
}
Al final, puede recorrer toda la lista y comprobar qué objetos, isSelected es verdadero
El problema es que la vista del reciclador está reciclando (como su nombre lo indica) sus vistas.
El sistema crea una cierta cantidad de ViewHolders para llenar su pantalla después de alcanzar esa cantidad que reutiliza los ViewHolders ya existentes.
Si configuró el botón marcado en su primera entrada de lista y reutiliza ViewHolder para su séptima lista, el botón todavía se verificará (porque se estableció en ViewHolder).
Para solucionar este problema, debe establecer la apariencia predeterminada para sus entradas de lista en onBindViewHOlder cada vez.
Actualizar:
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+"");
}
});
}
Actualicé ligeramente tu nuevo enfoque, ¿quizás esto ayude?
En su clase modelo agregue
private int checkedId = -1;
public int getCheckedId() {
return checkedId;
}
public void setCheckedId(int checkedId) {
this.checkedId = checkedId;
}
y cambie onBindViewHolder en el adaptador como este:
@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());
}
Este problema se produce debido a un error en RecyclerView
o en algún lugar del SDK de Android. De todos modos, tomé el consejo de otra pregunta de SO: onCheckedChanged llamó automáticamente .
Para RadioGroup
, será un poco diferente. Hay dos formas de hacerlo. Recomiendo el primero ya que es plug-n-play.
establece
OnCheckedChangeListener
enRadioGroup
: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); } } });
o configure
onCheckedChangeListener
en todos losRadioButton
s dentro delRadioGroup
: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);
Modifique su onBindViewHolder()
para esto
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''s 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());
}
Deberia de funcionar. Si hay algún problema por favor hágamelo saber.
Puedes hacerlo de esta manera .....
dentro de su clase de frijoles agregue un campo diga
String final_answer;
public String getFinalAnswer(){
return final_answer;
}
public void setFinalAnswer(String final_answer){
this.final_answer = final_answer;
}
en adaptador .....
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;
}
}
});
}
Para obtener respuestas seleccionadas finalmente ... escriba este código en la actividad principal
public void getSelectedAnswers(){
for(int i=0;i<slist.length;i++){
//get selected answer
Log.i("answer",slist.get(i).getFinalAnswer());
}
}
RecyclerView vino sobre ListView y su propiedad principal que es Reutiliza las celdas mientras se desplaza hacia arriba y hacia abajo. Debido a esto, no se mueve mientras se desplaza, incluso si tiene muchos datos en su lista. Usted está teniendo problemas debido a la reutilización de las células en RecyclerView.
Puede superar este problema vinculando los datos de la lista RecyclerView a la clase modal con el método de obtención y establecimiento. Puede mostrar la checkbox
activada o desactivada en función de la posición de la celda y los datos correspondientes. En mi muestra, usé setOnClickListener
lugar de setOnCheckedChangeListenerto
para mostrar la casilla de verificación marcada o sin setOnCheckedChangeListenerto
.