viewholder seleccionar recyclerview item eventos eliminar elemento adaptador android android-recyclerview

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.

  1. establece OnCheckedChangeListener en 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. o configure onCheckedChangeListener en todos los RadioButton s dentro del 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);


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 .