简体   繁体   English

RecyclerView中的选定项目在滚动时发生更改

[英]Selected items in RecyclerView change on scrolling

I have a RecyclerView with each element representing an event. 我有一个RecyclerView,每个元素代表一个事件。 I want to let the user select events by clicking it. 我想让用户通过单击选择事件。 Once selected, the event(s) and a report button will be colored: 选择后,事件和报告按钮将变为彩色:

UI before performing a click: click here . 单击之前的用户界面: 单击此处

UI After performing a click: click here . 用户界面执行单击后: 单击此处

It's pretty simple and allegedly works; 这非常简单,并且据称有效。 I set an OnClickListener for each ViewHolder which is responsible for coloring the item, and when fired it's triggering another event in the owning activity named onOccurrenceSelected , which is responsible for changing the button's state. 我为每个负责为项目着色的ViewHolder设置一个OnClickListener ,并在触发该事件时触发名为onOccurrenceSelected的拥有活动中的另一个事件,该事件负责更改按钮的状态。

However, when scrolling through the RecyclerView's items, other irrelevant items are colored like their OnClickListener was triggered (though it wasn't), and when scrolling back the selected event is colored as not selected. 但是,滚动浏览RecyclerView的项目时,其他不相关的项目会被着色,就像触发了它们的OnClickListener一样(尽管不是),并且向后滚动时,选定的事件被着色为未选中。 While this is happening, the only event that's supposed to color the items is not triggered. 发生这种情况时,不会触发应该为项目着色的唯一事件。

Any explanation for such behavior? 对这种行为有任何解释吗? Thanks! 谢谢!

EDIT: Here are some relevant code from the adapter: 编辑:这是适配器的一些相关代码:

private List<Occurrence> mDataSet;
private Activity activity;

public <OccurrencesActivity extends OnOccurrenceSelectedListener> OccurrencesAdapter(OccurrencesActivity occurrencesActivity, List<Occurrence> occurrences) {
    this.activity = (android.app.Activity) occurrencesActivity;
    mDataSet = occurrences;
}

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
    Occurrence instance = mDataSet.get(position);
    ...
    setOnClickListener(holder, instance);
    }

private void setOnClickListener(final ViewHolder holder, final Occurrence occurrence) {
    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (!occurrence.isSelected()) {
                holder.itemView.setBackgroundColor(App.getContext().getResources().getColor(R.color.turquoise));
                holder.titleTextView.setTextColor(App.getContext().getResources().getColor(R.color.white));
                holder.statusTextView.setTextColor(App.getContext().getResources().getColor(R.color.white));
                holder.dateTextView.setTextColor(App.getContext().getResources().getColor(R.color.white));
                holder.timeTextView.setTextColor(App.getContext().getResources().getColor(R.color.white));
            } else {
                holder.itemView.setBackgroundColor(App.getContext().getResources().getColor(R.color.white));
                holder.titleTextView.setTextColor(App.getContext().getResources().getColor(R.color.turquoise));
                holder.statusTextView.setTextColor(App.getContext().getResources().getColor(R.color.grey));
                holder.dateTextView.setTextColor(App.getContext().getResources().getColor(R.color.grey));
                holder.timeTextView.setTextColor(App.getContext().getResources().getColor(R.color.grey));
            }
            occurrence.setSelected(!occurrence.isSelected());

            ((OnOccurrenceSelectedListener)activity).onOccurrenceSelected(mDataSet);
        }
    });
}

Recyclerview always resuse views while scrolling so you have to store selected positions into temporary arraylist and then keep condition check into onBindViewHolder that whether that particular position is already exists in arraylist or not? Recyclerview总是在滚动时重用视图,因此您必须将选定的位置存储到临时arraylist中,然后将条件检查保持在onBindViewHolder中,以确保该特定位置是否已经存在于arraylist中? I updated your adaper. 我更新了你的衣服。 find the below changes with comment 在评论中找到以下变化

    private List<Occurrence> mDataSet;
private Activity activity;

//Added here temporary ArrayList
private ArrayList<String> mSelectedPosition = new ArrayList<String>;

public <OccurrencesActivity extends OnOccurrenceSelectedListener> OccurrencesAdapter(OccurrencesActivity occurrencesActivity, List<Occurrence> occurrences) {
    this.activity = (android.app.Activity) occurrencesActivity;
    mDataSet = occurrences;
}

@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {


    //Set ViewTag
    holder.itemView.setTag(position);

    //Check everyposition during view binding process
    if(mSelectedPosition.contains(String.valueOf(position))){

     holder.itemView.setBackgroundColor(App.getContext().getResources().getColor(R.color.white));
                holder.titleTextView.setTextColor(App.getContext().getResources().getColor(R.color.turquoise));
                holder.statusTextView.setTextColor(App.getContext().getResources().getColor(R.color.grey));
                holder.dateTextView.setTextColor(App.getContext().getResources().getColor(R.color.grey));
                holder.timeTextView.setTextColor(App.getContext().getResources().getColor(R.color.grey));


     }else{
    holder.itemView.setBackgroundColor(App.getContext().getResources().getColor(R.color.white));
                    holder.titleTextView.setTextColor(App.getContext().getResources().getColor(R.color.turquoise));
                    holder.statusTextView.setTextColor(App.getContext().getResources().getColor(R.color.grey));
                    holder.dateTextView.setTextColor(App.getContext().getResources().getColor(R.color.grey));
                    holder.timeTextView.setTextColor(App.getContext().getResources().getColor(R.color.grey));

      }

    Occurrence instance = mDataSet.get(position);
    ...
    setOnClickListener(holder, instance);
    }

private void setOnClickListener(final ViewHolder holder, final Occurrence occurrence) {
    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

       // Get Position
         int position = (int) view.getTag();

            //Remove SelectedPosition if Already there
              if(mSelectedPosition.contains(position))
                  mSelectedPosition.remove(String.valueOf(position));
               else
                  mSelectedPosition.add(String.valueOf(position));

                notifyDataSetChanged();

               //Not sure about this lines 
                occurrence.setSelected(!occurrence.isSelected());

                ((OnOccurrenceSelectedListener)activity).onOccurrenceSelected(mDataSet);
            }
        });
    }

Its the default behaviour of recyclerview. 它是recyclerview的默认行为。 it will recycle/reuse views which are not in use currently. 它将回收/重用当前未使用的视图。 If you want to save the state which is colored or not. 如果要保存有色或无色的状态。 Then save a parameter in your List<Object> per position. 然后在每个位置的List<Object>保存一个参数。 and as per position in onBindViewHolder method use that position to change the color. 并根据onBindViewHolder方法中的位置使用该位置更改颜色。

Try by Setting Tag to your item in onBindViewHolder of Adapter 通过在适配器的onBindViewHolder标签设置为您的项目来onBindViewHolder

holder.yourItem.setTag(position);

And then Inside the onClickListener ,Just save that position in shared Pref. 然后在onClickListener内部,只需将该位置保存在共享的Pref中。 if it's selected, whenever you set adapter then before setting values just check that is it selected or not based on shared Pref. 如果已选择,则每当您设置适配器,然后在设置值之前,只需基于共享的Pref检查它是否已选择。 and perform action for same. 并执行相同的操作。

public void onClick(View view) {
    if (!occurrence.isSelected()) {
        //save position in share pref.
    } 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM