带有动画的Android recyclerview问题

时间:2016-09-10 15:14:56

标签: android animation position android-recyclerview

我正在尝试在recyclerview中扩展cardviews。我让扩展部分工作,但是当添加转换时,一些视觉错误开始发生。当没有屏幕外项目时,转换工作正常,但是当我向Recyclerview添加超过(在我的情况下)4个项目时,它开始发生。

GIF with 4 items

GIF with more than 4 items

当禁用过渡动画时,cardview扩展可以正常使用4个以上的项目。我认为问题与职位变化有关,但我无法找到解决问题的方法。

我用于实现cardview扩展的指南可以在这里找到:https://stackoverflow.com/a/38623873/6673949

我完整的recyclerview适配器

public class BasketRecyclerAdapter extends RecyclerView.Adapter<BasketRecyclerAdapter.CustomViewHolder> {
private String letter;
private Context mContext;
private ColorGenerator generator = ColorGenerator.MATERIAL;
private List<Basket> baskets;
private int mExpandedPosition = -1;
private RecyclerView r1;

public BasketRecyclerAdapter(Context context, List<Basket> baskets, RecyclerView r1) {
    this.mContext = context;
    this.baskets = baskets;
    this.r1 = r1;

}

@Override
public CustomViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.basket_menu_item, null);
    CustomViewHolder viewHolder = new CustomViewHolder(view);
    return viewHolder;
}

@Override
public void onBindViewHolder(final BasketRecyclerAdapter.CustomViewHolder holder, final int position) {

    String basketName = baskets.get(position).getBasketName();

    holder.basketName.setText(basketName);

    letter = "" + basketName.charAt(0);

    TextDrawable drawable = TextDrawable.builder()
            .buildRound(letter, generator.getColor(basketName));


    holder.imageLetter.setImageDrawable(drawable);

    final boolean isExpanded = position == mExpandedPosition;
    holder.expandedLayout.setVisibility(isExpanded?View.VISIBLE:View.GONE);
    holder.itemView.setActivated(isExpanded);
    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mExpandedPosition = isExpanded ? -1:position;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                TransitionManager.beginDelayedTransition(r1);
            }
            notifyDataSetChanged();
        }
    });


}

可以采取哪些措施来解决问题?感谢。

编辑:我试图通过使用ListView而不是RecyclerView来实现它,但ListView适配器不会使用相同的代码进行扩展 - 将尝试找出原因。

Edit2:通过使用另一个名为“ExpandableLayout”的库来实现它,但似乎仍无法弄清楚为什么没有其他库就无法工作。

3 个答案:

答案 0 :(得分:1)

我有类似的问题。 添加适配器:

@Override
public long getItemId(int position) {
    return position;
}

myAdapter.setHasStableIds(true);

答案 1 :(得分:1)

我有类似的问题。当屏幕外没有任何项目时它工作正常,但是当你有屏幕外的项目时,动画无法正常工作。解决方案是不使用notifyDataSetChanged()更新适配器中的每个项目。您只需要更新要展开的位置和要折叠的位置。我的猜测是,屏幕上的项目ViewHolders正在弄乱动画。

    final boolean isExpanded = position == mExpandedPosition;
    vh.expandableView.setVisibility(isExpanded ? View.VISIBLE : View.GONE);
    vh.itemView.setActivated(isExpanded);
    vh.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            // collapse any currently expanded items
            if (mExpandedPosition != RecyclerView.NO_POSITION) {
                notifyItemChanged(mExpandedPosition);
            }

            //Update expanded position
            mExpandedPosition = isExpanded ? -1 : position;

            TransitionManager.beginDelayedTransition(mRecyclerView);

            //Expand new item clicked
            notifyItemChanged(position);

        }
    });

答案 2 :(得分:1)

我有同样的问题。这就是我的工作方式,就像您在GIF with 4 items上显示的一样:)

在您的自定义适配器中,添加 notifyItemChanged(位置) notifyItemChanged(previousExpandedPosition),而不是 notifyDataSetChanged()

public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
    final boolean isExpanded = position==mExpandedPosition;

    holder.expandedLayout.setVisibility(isExpanded ? View.VISIBLE : View.GONE);
    holder.itemView.setActivated(isExpanded);

    if (isExpanded)
        mPreviousExpandedPosition = position;

    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mExpandedPosition = isExpanded ? -1:position;
            TransitionManager.beginDelayedTransition(mRecyclerView);

            notifyItemChanged(mPreviousExpandedPosition);
            notifyItemChanged(position);
        }
    });
}

声明全局变量 mExpandedPosition mPreviousExpandedPosition 并将其初始化为-1。

在适配器的构造函数中将 mRecyclerView 作为参数传递。

在为循环视图设置适配器之后,在片段或活动中设置 mRecyclerView.setItemAnimator(null)

mRecyclerView.setAdapter(mRecyclerViewAdapter);
mRecyclerView.setItemAnimator(null);

这应该可以解决您的问题。