RecyclerView - changing selected item icon needs two clicks to work

落爺英雄遲暮 提交于 2021-01-28 06:08:10

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!