RecyclerView 每隔几个项目都是一样的——可扩展项目
RecyclerView every few items are the same - expandable item
我对 recyclerView 有疑问。我正在使用此布局在 recyclerView 中扩展 cardView:https://github.com/AAkira/ExpandableLayout .
如果我点击某个项目展开,然后向下滚动,每第 7 个元素也会展开。我能做些什么来阻止这种影响?我知道这是因为 recyclerView 记住视图持有者的状态,并且方法 onBindiewHolder 中的 mIsViewExpanded 每 7 个项目设置为 true。提前感谢任何解决方案!
这是我的 viewholder 的代码:
class EventsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private ImageView edit, cancel, expandIcon;
private ExpandableLayout expandableArea;
private boolean mIsViewExpanded = false;
public EventsViewHolder(View itemView) {
super(itemView);
expandIcon = (ImageView) itemView.findViewById(R.id.card_item_expand_icon);
expandIcon.setOnClickListener(this);
//divider = (View) itemView.findViewById(R.id.event_card_divider);
}
private void collapseArea(){
expandableArea.collapse();
edit.setVisibility(View.GONE);
cancel.setVisibility(View.GONE);
mIsViewExpanded = false;
expandIcon.setImageResource(R.drawable.vector_drawable_ic_expand_more_black___px);
}
private void expandArea(){
expandableArea.expand();
edit.setVisibility(View.VISIBLE);
cancel.setVisibility(View.VISIBLE);
mIsViewExpanded = true;
expandIcon.setImageResource(R.drawable.vector_drawable_ic_expand_less_black___px);
}
@Override
public void onClick(View view) {
if(mIsViewExpanded){
collapseArea();
isItemExpanded[getAdapterPosition()] = false;
}
else {
expandArea();
isItemExpanded[getAdapterPosition()] = true;
}
}
}
当我单击 CardView 内的图标时,expandableArea 会根据 mIsViewExpanded 值展开或折叠。
编辑。
适配器代码:
public class EventsRecyclerViewAdapter extends RecyclerView.Adapter<EventsRecyclerViewAdapter.EventsViewHolder> implements PopupMenu.OnMenuItemClickListener, PopupMenu.OnDismissListener {
public interface EventsRecyclerViewAdapterInterface {
public void emptyAdapter();
public void itemDeleted(int id);
}
private List<Event> listData = new ArrayList<>();
private LayoutInflater inflater;
private MainActivity context;
private View view;
private int positionToCancel;
private boolean[] isItemExpanded;
private EventsRecyclerViewAdapterInterface deleteListener;
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
removeItem(positionToCancel);
return true;
}
@Override
public void onDismiss(PopupMenu menu) {
menu.dismiss();
}
public EventsRecyclerViewAdapter(Activity context, EventsRecyclerViewAdapterInterface deleteListener) {
this.inflater = LayoutInflater.from(context);
this.context = (MainActivity) context;
this.deleteListener = deleteListener;
}
@Override
public EventsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
view = inflater.inflate(R.layout.item_event_card, parent, false);
return new EventsViewHolder(view);
}
@Override
public void onBindViewHolder(EventsViewHolder holder, int position) {
Event item = listData.get(position);
if(!isItemExpanded[position]){
if(holder.mIsViewExpanded){
holder.collapseArea();
}
}
else {
holder.expandArea();
}
holder.title.setText(item.getName());
holder.place.setText(item.getLocation());
DateTimeFormatter formatter = DateTimeFormat.forPattern(StaticValues.DATE_TIME_PATTERN_FOR_VIEW);
holder.time.setText(formatter.print(item.getDate()));
holder.edit.setOnClickListener(view1 -> takeDetailsEvent(item));
holder.cancel.setOnClickListener(view1 -> {
positionToCancel = position;
MyPopupMenu popup = new MyPopupMenu(view1.getContext(), view1, context);
popup.inflate(R.menu.event_delete_menu);
popup.setOnMenuItemClickListener(this);
popup.setOnDismissListener(this);
popup.show();
});
holder.container.setOnClickListener(view1 -> {
Intent intent = new Intent(view1.getContext(), EventDetailsActivity.class);
intent.putExtra("eventId", item.getApiId());
view1.getContext().startActivity(intent);
});
}
private void removeItem(int position) {
deleteListener.itemDeleted(listData.get(position).getApiId());
listData.remove(position);
notifyDataSetChanged();
if (getItemCount() == 0) {
deleteListener.emptyAdapter();
}
}
private void takeDetailsEvent(Event event) {
Intent intent = new Intent(view.getContext(), CreateEventActivity.class);
intent.putExtra("id", event.getApiId());
view.getContext().startActivity(intent);
}
public void setListData(List<Event> eventList) {
listData = eventList;
isItemExpanded = new boolean[listData.size()];
notifyDataSetChanged();
}
@Override
public int getItemCount() {
return listData.size();
}
}
这就是我现在的处理方式。在适配器 class 中,我有一个布尔数组,其长度与 listData 相同。在与列表项对应的位置上,我保留值:展开时为 true,折叠时为 false。在 onBindViewHolder 中,我检查位置是否已展开,如果没有,我会折叠它。这不是理想的解决方案,因为在滚动期间项目正在折叠并且看起来不太好。
RecyclerView
不会创建新视图,而是在滚动时重复使用现有视图 (ScrappedViews
)。所以发生的事情是当你展开 CardView
并滚动时,由于 CardView
被重复使用,你会得到另一个展开的视图。
所以只需 collapse/expand 您 Adapter
的 onBindView()
中的视图,为此您需要将状态与适配器列表中的每个项目相关联。
简单地解决滚动过程中的 expand/collapse 动画 setDuration(0)
这允许您 expand/collapse 没有任何延迟或动画以获得更流畅的滚动体验。
这是 recyclerView 的预期行为。 RecyclerView 回收不在视图中的项目。如果您不想回收您的物品,请使用 holder.setIsRecyclable(false);在适配器的 onBindViewHolder() 方法中。
holder.setIsRecyclable(false);
在您的适配器中覆盖这 2 个方法。
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemViewType(int position) {
return position;
}
参考=How to prevent items from getting duplicated when scrolling recycler view
我对 recyclerView 有疑问。我正在使用此布局在 recyclerView 中扩展 cardView:https://github.com/AAkira/ExpandableLayout .
如果我点击某个项目展开,然后向下滚动,每第 7 个元素也会展开。我能做些什么来阻止这种影响?我知道这是因为 recyclerView 记住视图持有者的状态,并且方法 onBindiewHolder 中的 mIsViewExpanded 每 7 个项目设置为 true。提前感谢任何解决方案!
这是我的 viewholder 的代码:
class EventsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private ImageView edit, cancel, expandIcon;
private ExpandableLayout expandableArea;
private boolean mIsViewExpanded = false;
public EventsViewHolder(View itemView) {
super(itemView);
expandIcon = (ImageView) itemView.findViewById(R.id.card_item_expand_icon);
expandIcon.setOnClickListener(this);
//divider = (View) itemView.findViewById(R.id.event_card_divider);
}
private void collapseArea(){
expandableArea.collapse();
edit.setVisibility(View.GONE);
cancel.setVisibility(View.GONE);
mIsViewExpanded = false;
expandIcon.setImageResource(R.drawable.vector_drawable_ic_expand_more_black___px);
}
private void expandArea(){
expandableArea.expand();
edit.setVisibility(View.VISIBLE);
cancel.setVisibility(View.VISIBLE);
mIsViewExpanded = true;
expandIcon.setImageResource(R.drawable.vector_drawable_ic_expand_less_black___px);
}
@Override
public void onClick(View view) {
if(mIsViewExpanded){
collapseArea();
isItemExpanded[getAdapterPosition()] = false;
}
else {
expandArea();
isItemExpanded[getAdapterPosition()] = true;
}
}
}
当我单击 CardView 内的图标时,expandableArea 会根据 mIsViewExpanded 值展开或折叠。
编辑。 适配器代码:
public class EventsRecyclerViewAdapter extends RecyclerView.Adapter<EventsRecyclerViewAdapter.EventsViewHolder> implements PopupMenu.OnMenuItemClickListener, PopupMenu.OnDismissListener {
public interface EventsRecyclerViewAdapterInterface {
public void emptyAdapter();
public void itemDeleted(int id);
}
private List<Event> listData = new ArrayList<>();
private LayoutInflater inflater;
private MainActivity context;
private View view;
private int positionToCancel;
private boolean[] isItemExpanded;
private EventsRecyclerViewAdapterInterface deleteListener;
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
removeItem(positionToCancel);
return true;
}
@Override
public void onDismiss(PopupMenu menu) {
menu.dismiss();
}
public EventsRecyclerViewAdapter(Activity context, EventsRecyclerViewAdapterInterface deleteListener) {
this.inflater = LayoutInflater.from(context);
this.context = (MainActivity) context;
this.deleteListener = deleteListener;
}
@Override
public EventsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
view = inflater.inflate(R.layout.item_event_card, parent, false);
return new EventsViewHolder(view);
}
@Override
public void onBindViewHolder(EventsViewHolder holder, int position) {
Event item = listData.get(position);
if(!isItemExpanded[position]){
if(holder.mIsViewExpanded){
holder.collapseArea();
}
}
else {
holder.expandArea();
}
holder.title.setText(item.getName());
holder.place.setText(item.getLocation());
DateTimeFormatter formatter = DateTimeFormat.forPattern(StaticValues.DATE_TIME_PATTERN_FOR_VIEW);
holder.time.setText(formatter.print(item.getDate()));
holder.edit.setOnClickListener(view1 -> takeDetailsEvent(item));
holder.cancel.setOnClickListener(view1 -> {
positionToCancel = position;
MyPopupMenu popup = new MyPopupMenu(view1.getContext(), view1, context);
popup.inflate(R.menu.event_delete_menu);
popup.setOnMenuItemClickListener(this);
popup.setOnDismissListener(this);
popup.show();
});
holder.container.setOnClickListener(view1 -> {
Intent intent = new Intent(view1.getContext(), EventDetailsActivity.class);
intent.putExtra("eventId", item.getApiId());
view1.getContext().startActivity(intent);
});
}
private void removeItem(int position) {
deleteListener.itemDeleted(listData.get(position).getApiId());
listData.remove(position);
notifyDataSetChanged();
if (getItemCount() == 0) {
deleteListener.emptyAdapter();
}
}
private void takeDetailsEvent(Event event) {
Intent intent = new Intent(view.getContext(), CreateEventActivity.class);
intent.putExtra("id", event.getApiId());
view.getContext().startActivity(intent);
}
public void setListData(List<Event> eventList) {
listData = eventList;
isItemExpanded = new boolean[listData.size()];
notifyDataSetChanged();
}
@Override
public int getItemCount() {
return listData.size();
}
}
这就是我现在的处理方式。在适配器 class 中,我有一个布尔数组,其长度与 listData 相同。在与列表项对应的位置上,我保留值:展开时为 true,折叠时为 false。在 onBindViewHolder 中,我检查位置是否已展开,如果没有,我会折叠它。这不是理想的解决方案,因为在滚动期间项目正在折叠并且看起来不太好。
RecyclerView
不会创建新视图,而是在滚动时重复使用现有视图 (ScrappedViews
)。所以发生的事情是当你展开 CardView
并滚动时,由于 CardView
被重复使用,你会得到另一个展开的视图。
所以只需 collapse/expand 您 Adapter
的 onBindView()
中的视图,为此您需要将状态与适配器列表中的每个项目相关联。
简单地解决滚动过程中的 expand/collapse 动画 setDuration(0)
这允许您 expand/collapse 没有任何延迟或动画以获得更流畅的滚动体验。
这是 recyclerView 的预期行为。 RecyclerView 回收不在视图中的项目。如果您不想回收您的物品,请使用 holder.setIsRecyclable(false);在适配器的 onBindViewHolder() 方法中。
holder.setIsRecyclable(false);
在您的适配器中覆盖这 2 个方法。
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemViewType(int position) {
return position;
}
参考=How to prevent items from getting duplicated when scrolling recycler view