Проблема с выбором элемента RecyclerView для Android

#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? Если я не объявляю его окончательным, отображаются ошибки…..