可扩展的RecyclerView问题

时间:2018-01-12 11:38:30

标签: android android-recyclerview

我有一个recyclelerview,onClick展开项目以显示描述。

它可以正常展开和折叠,但是当我使用展开的项目滚动时,展开的一些新项目会被展开......

例如,我有一个包含50个项目的回收者视图。我扩展了第一个项目和向下滚动,每个项目都有一个扩展项目。

public class NotificationsExpandAdapter extends RecyclerView.Adapter<NotificationsExpandAdapter.NotificationsViewHolder> {

    private ListItemClickListener mOnClickListener;
    private ArrayList<SchoolNotification> mNotifications;
    private HashMap<String, String> typeNotifications;

    public interface ListItemClickListener {
        void onListItemClick(SchoolNotification notification);
    }

    public NotificationsExpandAdapter(ArrayList<SchoolNotification> notifications, Resources resources) {
        mNotifications = notifications;
        typeNotifications = eventsType(resources);
    }

    public NotificationsExpandAdapter(ArrayList<SchoolNotification> notifications, Resources resources, ListItemClickListener listener) {
        mNotifications = notifications;
        mOnClickListener = listener;
        typeNotifications = eventsType(resources);
    }

    @Override
    public NotificationsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        Context context = viewGroup.getContext();
        int layoutIdForListItem = R.layout.notification_list_item_expand;
        LayoutInflater inflater = LayoutInflater.from(context);
        boolean shouldAttachToParentImmediately = false;

        View view = inflater.inflate(layoutIdForListItem, viewGroup, shouldAttachToParentImmediately);
        NotificationsViewHolder viewHolder = new NotificationsViewHolder(view);

        return viewHolder;
    }

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

        holder.mNotificationDate.setText(formatDateDayMonth(mNotifications.get(position).getDate()));
        holder.mNotificationType.setText(typeNotifications.get(mNotifications.get(position).getType()));
        holder.mNotificationTitle.setText(mNotifications.get(position).getTitle());
        holder.mNotificationDescription.setText(mNotifications.get(position).getDescription());
        if (mNotifications.get(position).getSubject().getName() != null) {
            holder.mNotificationSubject.setText(mNotifications.get(position).getSubject().getName());
        }
    }

    public SchoolNotification getItem(Integer position){
        return mNotifications.get(position);
    }

    @Override
    public int getItemCount() {
        return mNotifications.size();
    }


    class NotificationsViewHolder extends RecyclerView.ViewHolder
            implements OnClickListener {

        TextView listItemNumberView;
        TextView mNotificationDate;
        TextView mNotificationType;
        TextView mNotificationSubject;
        TextView mNotificationTitle;
        TextView mNotificationDescription;


        public NotificationsViewHolder(View itemView) {
            super(itemView);

            mNotificationDate = (TextView) itemView.findViewById(R.id.tv_notif_date);
            mNotificationType = (TextView) itemView.findViewById(R.id.tv_notif_type);
            mNotificationSubject = (TextView) itemView.findViewById(R.id.tv_notif_subject);
            mNotificationTitle = (TextView) itemView.findViewById(R.id.tv_notif_tittle);
            mNotificationDescription = (TextView) itemView.findViewById(R.id.tv_notif_description);
            mNotificationDescription.setVisibility(View.GONE);

            itemView.setOnClickListener(this);
        }


        void bind(int listIndex) {
            listItemNumberView.setText(String.valueOf(listIndex));
        }


        @Override
        public void onClick(View v) {


            if(mNotificationDescription.isShown()){
                Utils.slide_up(v.getContext(), mNotificationDescription);
                mNotificationDescription.setVisibility(View.GONE);
            }
            else{
                mNotificationDescription.setVisibility(View.VISIBLE);
                Utils.slide_down(v.getContext(), mNotificationDescription);
            }


//            mNotificationDescription.setVisibility(mNotificationDescription.isShown() ? View.GONE : View.VISIBLE);
//            if (mOnClickListener != null){
//                int clickedPosition = getAdapterPosition();
//                mOnClickListener.onListItemClick(mNotifications.get(clickedPosition));
//            }
        }
    }
}

2 个答案:

答案 0 :(得分:1)

ViewHolders被重用以提高列表的性能,因此他们会记住它们的状态。这就是为什么有些项目会展开的原因:他们重复使用ViewHolders,它们之前已经扩展过了。为了避免这个问题,你以某种方式记住哪些项目被扩展(例如,保存它们在ArrayList中的位置)并执行onBindViewHolder检查:如果项目被扩展(这样的位置存在于ArryaList中) - 展开它如果它没有 - 崩溃它。

答案 1 :(得分:0)

解。

在适配器类中添加了一个hashmap,在holder类中添加了id

public class NotificationsExpandAdapter extends RecyclerView.Adapter<NotificationsExpandAdapter.NotificationsViewHolder> {

    private ListItemClickListener mOnClickListener;
    private ArrayList<SchoolNotification> mNotifications;
    private HashMap<String, String> typeNotifications;
    private HashMap<Long, Boolean> expandedNotifications = new HashMap<>();

    public interface ListItemClickListener {
        void onListItemClick(SchoolNotification notification);
    }

    public NotificationsExpandAdapter(ArrayList<SchoolNotification> notifications, Resources resources) {
        mNotifications = notifications;
        typeNotifications = eventsType(resources);
    }

    public NotificationsExpandAdapter(ArrayList<SchoolNotification> notifications, Resources resources, ListItemClickListener listener) {
        mNotifications = notifications;
        mOnClickListener = listener;
        typeNotifications = eventsType(resources);
    }


    @Override
    public NotificationsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        Context context = viewGroup.getContext();
        int layoutIdForListItem = R.layout.notification_list_item_expand;
        LayoutInflater inflater = LayoutInflater.from(context);
        boolean shouldAttachToParentImmediately = false;

        View view = inflater.inflate(layoutIdForListItem, viewGroup, shouldAttachToParentImmediately);
        NotificationsViewHolder viewHolder = new NotificationsViewHolder(view);

        return viewHolder;
    }


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

        holder.id = mNotifications.get(position).getId();
        holder.mNotificationDate.setText(formatDateDayMonth(mNotifications.get(position).getDate()));
        holder.mNotificationType.setText(typeNotifications.get(mNotifications.get(position).getType()));
        holder.mNotificationTitle.setText(mNotifications.get(position).getTitle());
        holder.mNotificationDescription.setText(mNotifications.get(position).getDescription());
        if (mNotifications.get(position).getSubject().getName() != null) {
            holder.mNotificationSubject.setText(mNotifications.get(position).getSubject().getName());
        }
        if (expandedNotifications.containsKey(holder.id))
            holder.mNotificationDescription.setVisibility(View.VISIBLE);
        else
            holder.mNotificationDescription.setVisibility(View.GONE);

    }

    public SchoolNotification getItem(Integer position){
        return mNotifications.get(position);
    }

    @Override
    public int getItemCount() {
        return mNotifications.size();
    }


    class NotificationsViewHolder extends RecyclerView.ViewHolder
            implements OnClickListener {

        TextView listItemNumberView;
        TextView mNotificationDate;
        TextView mNotificationType;
        TextView mNotificationSubject;
        TextView mNotificationTitle;
        TextView mNotificationDescription;
        Long id;


        public NotificationsViewHolder(View itemView) {
            super(itemView);

            mNotificationDate = (TextView) itemView.findViewById(R.id.tv_notif_date);
            mNotificationType = (TextView) itemView.findViewById(R.id.tv_notif_type);
            mNotificationSubject = (TextView) itemView.findViewById(R.id.tv_notif_subject);
            mNotificationTitle = (TextView) itemView.findViewById(R.id.tv_notif_tittle);
            mNotificationDescription = (TextView) itemView.findViewById(R.id.tv_notif_description);
            mNotificationDescription.setVisibility(View.GONE);

            itemView.setOnClickListener(this);
        }


        void bind(int listIndex) {
            listItemNumberView.setText(String.valueOf(listIndex));
        }


        @Override
        public void onClick(View v) {


            if(mNotificationDescription.isShown()){
                Utils.slide_up(v.getContext(), mNotificationDescription);
                mNotificationDescription.setVisibility(View.GONE);
                expandedNotifications.remove(id);
            }
            else{
                mNotificationDescription.setVisibility(View.VISIBLE);
                Utils.slide_down(v.getContext(), mNotificationDescription);
                expandedNotifications.put(id, true);
            }
        }
    }
}