-->

Recycler View Wrongly selecting View Item while pe

2019-08-21 09:07发布

问题:

I have implemented an recycler view with Multi Select successfully using addOnItemTouchListener for identifying and selecting using single and double click.When i have Less than 5 items int the recycler view,Everything works fine but when i have more data,to be exact when the recycler view starts recycling the view,my selection is going crazy and it selects differnt possition.I logged out to see the clicking position,those seems to be right but something is not right which makes my selection wrong.I'm new to programming and to android app development.Can anyone take alot at this and help me out please,Here is my code

My adapter class

public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactHolder> implements SectionIndexer, Filterable {

    public List<Contact> contactList;
    List<Contact> filteredUsersList;
    CustomFilter filter;
    Context mContext;
    int itemResource;
    ArrayList<Contact> selected_usersList = new ArrayList<>();
    int pos;

    private ArrayList<Integer> mSectionPositions;

    ContactAdapter(Context mContext, int itemResource, List<Contact> contactList, ArrayList<Contact> selectedList) {
        this.contactList = contactList;
        this.mContext = mContext;
        this.itemResource = itemResource;
        this.selected_usersList = selectedList;
        this.filteredUsersList = contactList;
    }

    @Override
    public ContactHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(itemResource, parent, false);
        return new ContactHolder(v);
    }

    @Override
    public void onBindViewHolder(final ContactHolder holder, int position) {
        pos = position;
        final Contact contact = contactList.get(pos);

        holder.colg.setText(contact.getColg());
        holder.name.setText(contact.getName());
        holder.job.setText(contact.getJob());


        if (contact.getImage() != null)
            holder.img.setImageBitmap(Utility.getPhoto(contact.getImage()));


    }

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


    class ContactHolder extends RecyclerView.ViewHolder {

        private TextView name, colg, job, id, mentee, mentor, participant;
        private ImageView selected;
        // private PorterShapeImageView img;
        private HexagonMaskView img;
        private RelativeLayout rr_layout;
        ItemClickListener itemClickListener;

        ContactHolder(View itemView) {
            super(itemView);
            // Set up the UI widgets of the holder
            // img = (PorterShapeImageView) itemView.findViewById(R.id.contact_image);
            img = (HexagonMaskView) itemView.findViewById(R.id.contact_image);
            name = (TextView) itemView.findViewById(R.id.contact_name);
            colg = (TextView) itemView.findViewById(R.id.contact_colg);
            job = (TextView) itemView.findViewById(R.id.contact_job);
            mentee = (TextView) itemView.findViewById(R.id.mentee);
            mentor = (TextView) itemView.findViewById(R.id.mentor);
            participant = (TextView) itemView.findViewById(R.id.participant);
            rr_layout = (RelativeLayout) itemView.findViewById(R.id.rr_layout);
            selected = (ImageView) itemView.findViewById(R.id.tic_contact_selected);

        }

    }
}

My RecyclerItemClickListener Class

public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {

    public interface OnItemClickListener {
        void onItemClick(View view, int position);

        void onItemLongClick(View view, int position);
    }

    private OnItemClickListener mListener;
    private GestureDetector mGestureDetector;

    public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener) {
        mListener = listener;

        mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return true;
            }

            @Override
            public void onLongPress(MotionEvent e) {
                View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());

                if (childView != null && mListener != null) {
                    mListener.onItemLongClick(childView, recyclerView.getChildAdapterPosition(childView));
                }
            }
        });
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
        View childView = view.findChildViewUnder(e.getX(), e.getY());

        if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
            mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
        }

        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }
}

My Implementation of addOnItemTouchListener

    contactsRecyclerViewT.addOnItemTouchListener(new RecyclerItemClickListener(this, contactsRecyclerViewT, new RecyclerItemClickListener.OnItemClickListener() {
        @Override
        public void onItemClick(View view, final int position) {

            Log.e("tag", "" + position);

            for (int i = 0; i < multiselect_list.size(); i++) {
                Log.e("tag", "sss" + multiselect_list.get(i).getName());
            }

            pos = position;

            contact = contactArrayList.get(position);

            menteeTextView = (TextView) view.findViewById(R.id.mentee);
            mentorTextView = (TextView) view.findViewById(R.id.mentor);
            participantTextView = (TextView) view.findViewById(R.id.participant);
            rr_layout = (RelativeLayout) view.findViewById(R.id.rr_layout);
            selected = (ImageView) view.findViewById(R.id.tic_contact_selected);
            img = (HexagonMaskView) view.findViewById(R.id.contact_image);
            name = (TextView) view.findViewById(R.id.contact_name);

            if (isMultiSelect) {

                img.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {

                        multi_select(position);

                        if (multiselect_list.contains(contactArrayList.get(position))) {

                            contact.setStatus("0");
                            Log.e("tag", "setStatus" + contact.getStatus());

                            Log.e("tag", "position " + position);

                            rr_layout.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.bg_card_selected));
                            selected.setVisibility(View.VISIBLE);

                            mentorTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
                            participantTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
                            menteeTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorAccent));
                            menteeTextView.setVisibility(View.VISIBLE);
                            mentorTextView.setVisibility(View.VISIBLE);
                            participantTextView.setVisibility(View.VISIBLE);
                            menteeTextView.setClickable(true);
                            mentorTextView.setClickable(true);
                            participantTextView.setClickable(true);

                        } else {
                            rr_layout.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.cement));
                            selected.setVisibility(View.GONE);

                            Log.e("tag", "position " + position);

                            menteeTextView.setVisibility(View.GONE);
                            mentorTextView.setVisibility(View.GONE);
                            participantTextView.setVisibility(View.GONE);
                            menteeTextView.setClickable(false);
                            mentorTextView.setClickable(false);
                            participantTextView.setClickable(false);
                        }

                    }
                });

                mentorTextView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {

                        contact.setStatus("1");
                        Log.e("tag", "setStatus" + contact.getStatus());

                        mentorTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorAccent));
                        menteeTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
                        participantTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
                    }
                });


                menteeTextView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {

                        contact.setStatus("0");
                        Log.e("tag", "setStatus" + contact.getStatus());

                        mentorTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
                        participantTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
                        menteeTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorAccent));
                    }
                });


                participantTextView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {

                        contact.setStatus("2");
                        Log.e("tag", "setStatus" + contact.getStatus());

                        mentorTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
                        menteeTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
                        participantTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorAccent));
                    }
                });

                name.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Intent intent = new Intent(ContactsActivity.this, OtherProfileActivity.class);
                        intent.putExtra("id", Integer.parseInt(contactArrayList.get(position).getId()));
                        startActivity(intent);
                    }
                });

            } else {
                Intent intent = new Intent(ContactsActivity.this, OtherProfileActivity.class);
                intent.putExtra("id", Integer.parseInt(contactArrayList.get(position).getId()));
                startActivity(intent);
            }
            // contactList.get(position).setStatus("1");
            // contactList.get(position).setStatus("0");

        }

        @Override
        public void onItemLongClick(View view, int position) {

            contact = contactArrayList.get(position);

            Log.e("tag", "" + position);

            for (int i = 0; i < multiselect_list.size(); i++) {
                Log.e("tag", "sss" + multiselect_list.get(i).getName());
            }


            menteeTextView = (TextView) view.findViewById(R.id.mentee);
            mentorTextView = (TextView) view.findViewById(R.id.mentor);
            participantTextView = (TextView) view.findViewById(R.id.participant);
            rr_layout = (RelativeLayout) view.findViewById(R.id.rr_layout);
            selected = (ImageView) view.findViewById(R.id.tic_contact_selected);
            img = (HexagonMaskView) view.findViewById(R.id.contact_image);
            name = (TextView) view.findViewById(R.id.contact_name);

            if (!isMultiSelect) {
                multiselect_list = new ArrayList<>();
                isMultiSelect = true;

                if (mActionMode == null) {
                    mActionMode = startActionMode(mActionModeCallback);
                }
            }

            multi_select(position);

            if (multiselect_list.contains(contactArrayList.get(position))) {

                rr_layout.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.bg_card_selected));
                selected.setVisibility(View.VISIBLE);

                contact.setStatus("0");
                Log.e("tag", "setStatus" + contact.getStatus());

                Log.e("tag", "position " + position);

                mentorTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
                participantTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
                menteeTextView.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorAccent));
                menteeTextView.setVisibility(View.VISIBLE);
                mentorTextView.setVisibility(View.VISIBLE);
                participantTextView.setVisibility(View.VISIBLE);
                menteeTextView.setClickable(true);
                mentorTextView.setClickable(true);
                participantTextView.setClickable(true);

            } else {
                rr_layout.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.cement));
                selected.setVisibility(View.GONE);

                Log.e("tag", "position " + position);

                menteeTextView.setVisibility(View.GONE);
                mentorTextView.setVisibility(View.GONE);
                participantTextView.setVisibility(View.GONE);
                menteeTextView.setClickable(false);
                mentorTextView.setClickable(false);
                participantTextView.setClickable(false);
            }

        }
    }));

    ArrayList<AlphabetItem> mAlphabetItems = new ArrayList<>();
    List<String> strAlphabets = new ArrayList<>();
    for (int i = 0; i < contactArrayList.size(); i++) {
        Contact contact = contactArrayList.get(i);
        String name = contact.getName();
        if (name == null || name.trim().isEmpty())
            continue;
        String word = name.substring(0, 1);
        if (!strAlphabets.contains(word)) {
            strAlphabets.add(word);
            mAlphabetItems.add(new AlphabetItem(i, word, false));
        }
    }
}

回答1:

You are doing most of the view manipulation in Onclick listener, you should move that to you adapter onBindView, because even if you set in Onclick listener, it will modify when user scroll.

I am not giving complete view manipulation, I am just giving the hint how we should do.

@Override
public void onBindViewHolder(final ContactHolder holder, int position) {
    pos = position;
    final Contact contact = contactList.get(pos);

    holder.colg.setText(contact.getColg());
    holder.name.setText(contact.getName());
    holder.job.setText(contact.getJob());


    if (contact.getImage() != null)
        holder.img.setImageBitmap(Utility.getPhoto(contact.getImage()));


    if (multiselect_list.contains(contactArrayList.get(position))) { // May be you should check form your fragment or actvity using listeners
        holder.mentee.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));
        holder.participant.setBackgroundColor(ContextCompat.getColor(ContactsActivity.this, R.color.colorPrimary));

        holder.mentee.setVisibility(View.VISIBLE);
        holder.participant.setVisibility(View.VISIBLE);
    } else {

        holder.mentee.setVisibility(View.GONE);
        holder.participant.setVisibility(View.GONE);
    }

}


回答2:

add boolena array

boolean [] itemcheck;

initialize in constructor wit your arraylist.

  itemcheck = new boolean[feedItemList.size()];

check in bindview holder like this

 if(itemcheck[position]==true){ 
    holder.row_linearlayout.setBackgroundColor(Color.parseColor("#b7c5ea"));
        }else {
            holder.row_linearlayout.setBackgroundColor(0xFFFFFFFF);
            //holder.row_linearlayout.setBackgroundResource(R.drawable.blurback);
        }

and set ture or false onclick of your relativelayout controle instead of any other controle .

 holder.row_linearlayout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    LinearLayout Lout = (LinearLayout) v.findViewById(R.id.selectlinear);
                    if(model.isSelected()){
                        Lout.setBackgroundColor(0xFFFFFFFF);
                        itemcheck[position]=false;
                        //get all other controle value here
                    }else{

                        Lout.setBackgroundColor(Color.parseColor("#b7c5ea"));
                        itemcheck[position]=true;     
                      //get all other controle value here                  
                    }
                }
            });