RecyclerView每个项目都是相同的 - 可扩展项目

时间:2016-08-23 09:46:13

标签: android android-recyclerview expandablelistview

我对recyclerView有疑问。我正在使用此布局在recyclerView中扩展cardView:https://github.com/AAkira/ExpandableLayout

如果我点击某个项目进行展开,那么每7个元素也会向下滚动。我该怎么做才能阻止这种影响?我知道这是因为recyclelerView会记住视图持有者状态,并且方法onBindiewHolder中的mIsViewExpanded设置为每7个项目为true。提前感谢任何解决方案!

以下是我的观看者代码:

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值。

EDIT。 适配器代码:

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();
}

}

这就是我现在处理它的方式。在适配器类中,我有一个布尔数组,其中lenght与listData相同。在与列表项对应的位置上,我保持值:展开时为true,折叠时为false。在onBindViewHolder中,我检查位置是否展开,如果不是,我将其折叠。这不是理想的解决方案,因为在滚动项目崩溃期间它看起来不太好。

3 个答案:

答案 0 :(得分:2)

RecyclerView无法创建新视图,而是在滚动时重用现有视图(ScrappedViews)。所以当你展开CardView并滚动时会发生什么,因为CardView被重用,你会得到另一个展开的视图。

因此,只需在onBindView()的{​​{1}}中展开/展开视图,因为您需要将状态与适配器列表中的每个项目相关联。

要在滚动期间解决展开/折叠动画,只需Adapter即可展开/折叠,不会有任何延迟或动画,以获得更流畅的滚动体验。

答案 1 :(得分: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

答案 2 :(得分:0)

这是recyclerView的预期行为。 RecyclerView回收不在视图中的项目。如果您不希望您的物品被回收,请使用holder.setIsRecyclable(false);在适配器的onBindViewHolder()方法中。

holder.setIsRecyclable(false);