Как отслеживать выбранные элементы в RecyclerView в Android?

Как добиться последовательного выбора предметов с RecyclerView? Я понял всю идею RecyclerView переработка старых взглядов, а что нет. Моя проблема в том, что у меня есть список элементов со значком на каждом элементе, при нажатии на элемент значок меняет цвет. Мне удалось добиться всего этого, но я просто понял, когда прокручивал список, что у других элементов тоже изменились свои значки, и когда я прокручиваю назад к элементу, на котором я нажал, значок больше не отображается цвет".

Кто-нибудь знает, как отслеживать выбранные элементы? Я продолжаю видеть то, что называется SparseBooleanArray, но я не уверен, как это реализовать.

Вот мой код адаптера:

public class TableRVAdapter extends RecyclerView.Adapter<TableRVAdapter.TableHolder> {

    List<Tables> tableList;
    private SparseBooleanArray selectedItems;

    public TableRVAdapter(List<Tables> tableList)
    {
        this.tableList = tableList;
        selectedItems = new SparseBooleanArray();
       // setHasStableIds(true);
    }
    class TableHolder extends RecyclerView.ViewHolder
    {
        TextView tableTV;
        CardView tableCV;
        View circle;
        View parentView;
        TableHolder(final View itemView)
        {
            super(itemView);
            tableTV = (TextView)itemView.findViewById(R.id.tableTV);
            tableCV = (CardView)itemView.findViewById(R.id.tableCV);
            circle = itemView.findViewById(R.id.statusCircle);
            itemView.setClickable(true);
            parentView = itemView;

            tableCV.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                     circle.setBackgroundResource(R.drawable.circle);

                }
            });
        }
        /*
        @Override
        public void onClick(View view) {
            if (selectedItems.get(getAdapterPosition(), false)) {
                tableCV.setSelected(false);
                circle.setBackgroundResource(R.drawable.circle2);
            }
            else {
                selectedItems.put(getAdapterPosition(), true);
                tableCV.setSelected(true);
                circle.setBackgroundResource(R.drawable.circle);
            }

        }*/
    }

    @Override
    public TableHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.table_item,parent,false);
        TableHolder tableHolder = new TableHolder(view);
        return tableHolder;
    }

    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView)
    {
        super.onAttachedToRecyclerView(recyclerView);
    }


    @Override
    public void onBindViewHolder(TableHolder holder, int position) {
        holder.tableTV.setText(tableList.get(position).getTableNumber());

    }

    /**
     * Returns the total number of items in the data set hold by the adapter.
     *
     * @return The total number of items in this adapter.
     */
    @Override
    public int getItemCount() {
        return tableList.size();
    }

}

3 ответа

Решение

RecyclerView.adapter имеет 2 важные функции для переопределения:

onCreateViewHolder(parent, viewType)
onBindVIewHolder(viewholder, position)

Первая функция используется для надувания представлений, которые будут использоваться в представлении реселлера, вторая - для привязки данных, которые у вас есть, к этому представлению и, таким образом, для установки правильного состояния представления на представлении.

Само окно повторного просмотра будет только раздувать определенное количество просмотров, а затем начнет повторно использовать уже завышенные представления (следовательно, повторное представление). Поэтому вам нужно установить правильное состояние для каждого элемента в onBindViewholder() и использовать элемент в вашей коллекции в этой позиции, чтобы установить правильный viewState. Например: измените цвет значка в зависимости от логического значения в ваших объектах, например: isPressed

Я знаю, что на этот вопрос уже дан ответ, но кто-то может найти этот ответ полезным и более простым.

Существует один полезный метод в представлении переработчика: onViewRecycled,

Это может помочь вам уйти от нажатого состояния. При работе с изображениями / рисованными объектами в представлении recylcer, когда некоторые элементы не используют нарисованные объекты, будет отображаться нарисованное изображение предварительного просмотра, и оно будет выглядеть неправильно во всех данных, как это было с вами при выбранном представлении.

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

Например, вы помечаете фон выбранного элемента зеленым, а некоторые из ваших представлений содержат изображения (Примечание: только некоторые из ваших элементов), а затем используете этот метод следующим образом:

@Override
        public void onViewRecycled(MyViewHolder holder) {
            super.onViewRecycled(holder);

            // Set ImageView's Drawable as transperent
            holder.myImageView.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), android.R.color.transparent));

            // Set background color as transperent
            holder.bgContainer.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), android.R.color.transparent));

        }

И теперь вы можете управлять ArrayList целых чисел с идентификаторами / позицией выбранных элементов (используя метод onClick для элемента представления рециркулятора).

С onBindViewHolder(MyViewHolder myViewHolder, int position) Вы можете обычно заполнять данные. А для установки фона вы можете просто проверить, находится ли id / position в ArrayList или нет (если true, установите фоновый цвет зеленым, иначе оставьте его как есть. Так как он будет управляться методом onViewRecylcer и не повлияет на другие прокручиваемые элементы с зеленым фоном, даже если он не выбран).

Надеюсь, что это поможет кому-то и сделает обзор Recyler с выбором немного проще.

Вы должны сохранить экземпляр, как это

if (isPressed) {
    icon.setCustomIcon();
} else {
    icon.setDefaultIcon();    
}

если у вас есть пользовательский объект для логического isPressed или чего-то подобного, это должно работать

Другие вопросы по тегам