#java #android #android-recyclerview
#java #Android #android-recyclerview
Вопрос:
Я разрабатываю приложение для живой викторины, которое извлекает данные с сервера, и вопрос отображается в виде RecyclerView
, содержащем вопрос и четыре варианта. Теперь, когда я выбираю один вариант для данного вопроса, он выбирается правильно, но в то же время автоматически выбирается соответствующий вариант для другого вопроса.
Скриншот проблемы с выбором элемента выглядит следующим образом.
Вот класс адаптера моего RecyclerView
public class LiveTestAdapter extends RecyclerView.Adapter<LiveTestAdapter.CustomViewHolder>{
private int mItemSelected=-1;
private List<DmLiveQuiz> questionList;
DmLiveQuiz questionsList; // DmLiveQuiz questionsList
private Context context; //context
final DataHolder dh=new DataHolder();
public List<Integer> myResponse= new ArrayList<Integer>();
public int qno;
public String myQno;
public int afterSub;
DataHolder dataHolder;
public LiveTestAdapter(List<DmLiveQuiz> questionList, Context context) {
this.questionList = questionList;
this.context = context;
}
@NonNull
@Override
public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView= LayoutInflater.from(parent.getContext()).inflate(R.layout.live_quiz_display_format,parent,false);
return new CustomViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull final CustomViewHolder holder, int position) {
questionsList=questionList.get(holder.getAdapterPosition());
holder.tvQNo.setText(questionsList.getQuestionId() "");
holder.tvquestion.getLayoutParams().width= LinearLayout.LayoutParams.WRAP_CONTENT;
holder.tvquestion.setText(questionsList.getQuestion());
holder.optA.setText(questionsList.getOptA());
holder.optB.setText(questionsList.getOptB());
holder.optC.setText(questionsList.getOptC());
holder.optD.setText(questionsList.getOptD());
holder.optA.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
holder.optA.setBackgroundResource(R.drawable.button_border);
holder.optB.setBackgroundResource(R.drawable.button_question_style);
holder.optC.setBackgroundResource(R.drawable.button_question_style);
holder.optD.setBackgroundResource(R.drawable.button_question_style);
Toast toast = Toast.makeText(context, "Position :" holder.getAdapterPosition(), Toast.LENGTH_SHORT);
toast.show();
}
});
holder.optB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
holder.optA.setBackgroundResource(R.drawable.button_question_style);
holder.optB.setBackgroundResource(R.drawable.button_border);
holder.optC.setBackgroundResource(R.drawable.button_question_style);
holder.optD.setBackgroundResource(R.drawable.button_question_style);
Toast toast = Toast.makeText(context, "Position :" holder.getAdapterPosition(), Toast.LENGTH_SHORT);
toast.show();
}
});
holder.optC.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
holder.optA.setBackgroundResource(R.drawable.button_question_style);
holder.optB.setBackgroundResource(R.drawable.button_question_style);
holder.optC.setBackgroundResource(R.drawable.button_border);
holder.optD.setBackgroundResource(R.drawable.button_question_style);
Toast toast = Toast.makeText(context, "Position :" holder.getAdapterPosition(), Toast.LENGTH_SHORT);
toast.show();
}
});
holder.optD.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
holder.optA.setBackgroundResource(R.drawable.button_question_style);
holder.optB.setBackgroundResource(R.drawable.button_question_style);
holder.optC.setBackgroundResource(R.drawable.button_question_style);
holder.optD.setBackgroundResource(R.drawable.button_border);
Toast toast = Toast.makeText(context, "Position :" holder.getAdapterPosition(), Toast.LENGTH_SHORT);
toast.show();
}
});
holder.tvClear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
holder.optA.setBackgroundResource(R.drawable.button_question_style);
holder.optB.setBackgroundResource(R.drawable.button_question_style);
holder.optC.setBackgroundResource(R.drawable.button_question_style);
holder.optD.setBackgroundResource(R.drawable.button_question_style);
}
});
}
@Override
public int getItemCount() {
return questionList.size();
}
public class CustomViewHolder extends RecyclerView.ViewHolder{
TextView tvquestion, tvClear,tvQNo;
Button optA,optB,optC,optD;
public CustomViewHolder(View itemView) {
super(itemView);
tvQNo=(TextView)itemView.findViewById(R.id.tvLiveQuizQuestionNo);
tvquestion=(TextView)itemView.findViewById(R.id.tvLiveQuizQuestion);
optA=(Button)itemView.findViewById(R.id.buttonOptionA);
optB=(Button)itemView.findViewById(R.id.buttonOptionB);
optC=(Button)itemView.findViewById(R.id.buttonOptionC);
optD=(Button)itemView.findViewById(R.id.buttonOptionD);
tvClear=(TextView)itemView.findViewById(R.id.tvClearSelection);
}
}
}
Единственная проблема, с которой я сталкиваюсь, — это автоматический выбор оставшихся без ответа параметров.
Пожалуйста, помогите мне выбрать только выбранный вариант, а не те, которые не выбраны. Заранее спасибо.
Ответ №1:
Представления будут повторно использоваться в вашем RecyclerView
, и, следовательно, у вас возникла такая проблема. В вашем случае вы можете рассмотреть возможность создания другого массива, в котором хранятся ответы на ваши тесты и который может отслеживать каждый элемент в вашем RecyclerView
.
Я хотел бы предложить изменить ваш адаптер следующим образом. Я прокомментировал в некоторых местах. Надеюсь, это поможет вам понять вашу проблему.
public class LiveTestAdapter extends RecyclerView.Adapter<LiveTestAdapter.CustomViewHolder> {
private int mItemSelected = -1;
private List<DmLiveQuiz> questionList;
private int[] answerList; // Get a list of your answers here.
private DmLiveQuiz questionsList;
private Context context;
final DataHolder dh = new DataHolder();
public List<Integer> myResponse = new ArrayList<Integer>();
public int qno;
public String myQno;
public int afterSub;
DataHolder dataHolder;
public LiveTestAdapter(List<DmLiveQuiz> questionList, Context context) {
this.questionList = questionList;
this.context = context;
}
@NonNull
@Override
public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.live_quiz_display_format, parent, false);
return new CustomViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull final CustomViewHolder holder, int position) {
questionsList = questionList.get(holder.getAdapterPosition());
holder.tvQNo.setText(questionsList.getQuestionId() "");
holder.tvquestion.getLayoutParams().width = LinearLayout.LayoutParams.WRAP_CONTENT;
holder.tvquestion.setText(questionsList.getQuestion());
holder.optA.setText(questionsList.getOptA());
holder.optB.setText(questionsList.getOptB());
holder.optC.setText(questionsList.getOptC());
holder.optD.setText(questionsList.getOptD());
// Now you need to modify the backgrounds of your option buttons like the following.
if (answerList[position] == 1) holder.optA.setBackgroundResource(R.drawable.button_border);
else holder.optA.setBackgroundResource(R.drawable.button_question_style);
if (answerList[position] == 2) holder.optB.setBackgroundResource(R.drawable.button_border);
else holder.optB.setBackgroundResource(R.drawable.button_question_style);
if (answerList[position] == 3) holder.optC.setBackgroundResource(R.drawable.button_border);
else holder.optC.setBackgroundResource(R.drawable.button_question_style);
if (answerList[position] == 4) holder.optD.setBackgroundResource(R.drawable.button_border);
else holder.optD.setBackgroundResource(R.drawable.button_question_style);
holder.optA.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
holder.optA.setBackgroundResource(R.drawable.button_border);
answerList[position] = 1; // Selected first option which is A
Toast.makeText(context, "Position :" holder.getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
});
holder.optB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
holder.optB.setBackgroundResource(R.drawable.button_border);
answerList[position] = 2; // Selected second option which is B
Toast.makeText(context, "Position :" holder.getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
});
holder.optC.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
holder.optC.setBackgroundResource(R.drawable.button_border);
answerList[position] = 3; // Selected third option which is C
Toast.makeText(context, "Position :" holder.getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
});
holder.optD.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
holder.optD.setBackgroundResource(R.drawable.button_border);
answerList[position] = 4; // Selected fourth option which is D
Toast.makeText(context, "Position :" holder.getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
});
holder.tvClear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
holder.optA.setBackgroundResource(R.drawable.button_question_style);
holder.optB.setBackgroundResource(R.drawable.button_question_style);
holder.optC.setBackgroundResource(R.drawable.button_question_style);
holder.optD.setBackgroundResource(R.drawable.button_question_style);
answerList[position] = 0; // Clear the value in the answerList
}
});
}
// Use this function to set the question list in the adapter
public void setQuestionList(List<DmLiveQuiz> questionList) {
this.questionList = questionList;
this.answerList = new int[questionList.size()]; // This initializes the answer list having the same size as the question list
notifyDataSetChanged();
}
@Override
public int getItemCount() {
return questionList.size();
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
TextView tvquestion, tvClear, tvQNo;
Button optA, optB, optC, optD;
public CustomViewHolder(View itemView) {
super(itemView);
tvQNo = (TextView) itemView.findViewById(R.id.tvLiveQuizQuestionNo);
tvquestion = (TextView) itemView.findViewById(R.id.tvLiveQuizQuestion);
optA = (Button) itemView.findViewById(R.id.buttonOptionA);
optB = (Button) itemView.findViewById(R.id.buttonOptionB);
optC = (Button) itemView.findViewById(R.id.buttonOptionC);
optD = (Button) itemView.findViewById(R.id.buttonOptionD);
tvClear = (TextView) itemView.findViewById(R.id.tvClearSelection);
}
}
}
Обновление — Пожалуйста, проверьте, что я добавил setQuestionList
функцию в адаптер. Пожалуйста, используйте эту функцию для настройки списка вопросов. Потому что, я думаю, при инициализации вашего адаптера передаваемый список вопросов имеет нулевой размер.
Комментарии:
1. Спасибо за ваш быстрый ответ. После реализации предложенного вами кода я получаю следующую ошибку. E / AndroidRuntime: ФАТАЛЬНОЕ ИСКЛЮЧЕНИЕ: основной процесс: com.himsudha.agarni, PID: 28600 java.lang. Исключение NullPointerException: попытка чтения из нулевого массива в com.himsudha.agarni.adapters.LiveTestAdapter.onBindViewHolder(LiveTestAdapter.java:62) если (список ответов [позиция] == 1) holder.optA.setBackgroundResource(R.drawable.button_border); Это строка с ошибкой…….
2. Пожалуйста, попробуйте обновленный код. Я забыл инициализировать
answerList
переменную, и теперь это делается в конструкторе.3. Спасибо за ваш быстрый ответ и обновленный код, но теперь ошибка java.lang. Исключение ArrayIndexOutOfBoundsException: длина = 0; индекс = 0 отображается при if (список ответов [позиция] == 1) holder.optA.setBackgroundResource(R.drawable.button_border);
4. Пожалуйста, проверьте обновленный ответ. А также, пожалуйста, попробуйте найти ответ на некоторые ваши собственные тривиальные ошибки. В противном случае мы не сможем вам помочь.
5. Но вы не вызвали метод setQuestionList(). В какой позиции мне нужно это вызвать? Более того, у меня голова идет кругом, нужно ли мне объявлять переменную «position» в onBindViewHolder() как конечную позицию int? Если я не объявляю его окончательным, отображаются ошибки…..