问题
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
}
}
});
来源:https://stackoverflow.com/questions/45342165/recycler-view-wrongly-selecting-view-item-while-performing-multi-select