问题
I am working on a mailing app, in which user can send the same mail to multiple contacts. When I open the contacts list I want to be able to click on the user and his profile picture should be replaced with checked icon.
When I click to select a user the icon flickers and it does not change the first time I click on it. Second time I click on it the image still flickers, but then changes to checked, and every next time I click on that user it will flicker but do what I want - become checked/unchecked.
I am using this tutorial as a guide, but it is not documented as good as it should be. Some methods are explained in a single word, other not even mentioned, but appear in the code. I looked for other tutorials, and really found a lot of the same (identical) examples, without going even a bit deeper than the original.
Adapter.java:
@Override
public void onBindViewHolder(final ChooseContactsAdapter.ChooseContactsViewHolder holder, final int position) {
final Contact contact = contactList.get(position);
holder.userName.setText(contact.getUserName());
TextDrawable.IBuilder builder = TextDrawable.builder()
.beginConfig()
.withBorder(0)
.toUpperCase()
.endConfig()
.round();
ColorGenerator generator = ColorGenerator.MATERIAL;
// generate color based on a key (same key returns the same color), useful for list/grid views
int color = generator.getColor(contact.getUserId());
textDrawable = builder.build(contactList.get(position).getUserName().substring(0, 1), color);
holder.thumbNail.setImageDrawable(textDrawable);
holder.contactId = contact.getUserId();
// display profile image
applyProfilePicture(holder, contact);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// toggle selection
toggleSelection(position);
// Change background color of the selected items in list view
holder.itemView.setBackgroundColor(selectedItems.get(position) ? 0x9934B5E4 : Color.TRANSPARENT);
// check if item still exists
if (position != RecyclerView.NO_POSITION) {
Contact contact = contactList.get(position);
Toast.makeText(v.getContext(), "You clicked " + contact.getUserName(), Toast.LENGTH_SHORT).show();
}
// handle icon animation
applyIconAnimation(holder, position);
}
});
}
private void applyProfilePicture(ChooseContactsViewHolder holder, Contact contact) {
Picasso.with(context)
.load(AppConfig.URL_PROFILE_PHOTO + contact.getThumbnailUrl())
.placeholder(textDrawable)
.error(textDrawable)
.transform(new CircleTransform())
.into(holder.thumbNail);
}
private void applyIconAnimation(ChooseContactsViewHolder holder, int position) {
if (selectedItems.get(position, false)) {
holder.iconFront.setVisibility(View.GONE);
resetIconYAxis(holder.iconBack);
holder.iconBack.setVisibility(View.VISIBLE);
holder.iconBack.setAlpha(1);
if (currentSelectedIndex == position) {
FlipAnimator.flipView(context, holder.iconBack, holder.iconFront, true);
resetCurrentIndex();
}
} else {
holder.iconBack.setVisibility(View.GONE);
resetIconYAxis(holder.iconFront);
holder.iconFront.setVisibility(View.VISIBLE);
holder.iconFront.setAlpha(1);
if ((reverseAllAnimations && animationItemsIndex.get(position, false)) || currentSelectedIndex == position) {
FlipAnimator.flipView(context, holder.iconBack, holder.iconFront, false);
resetCurrentIndex();
}
}
}
private void toggleSelection(int pos) {
currentSelectedIndex = pos;
if (selectedItems.get(pos, false)) {
selectedItems.delete(pos);
animationItemsIndex.delete(pos);
} else {
selectedItems.put(pos, true);
animationItemsIndex.put(pos, true);
}
notifyItemChanged(pos);
}
回答1:
There's no need to call notifyItemChanged
on the toggleSelection
method. You are alredy changing the item manually with animations.
Calling notifyItemChanged
is what causes the flickering, because it interferes with the animations.
来源:https://stackoverflow.com/questions/47378085/recyclerview-changing-selected-item-icon-needs-two-clicks-to-work