[英]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.