【问题标题】:Android recyclerview issue with animationsAndroid recyclerview 动画问题
【发布时间】:2016-09-10 15:14:55
【问题描述】:

我正在尝试扩展 recyclerview 中的卡片视图。我得到了扩展部分的工作,但是当向它添加过渡时,开始出现一些视觉错误。当没有屏幕外项目时,过渡效果很好,但是当我向回收站视图添加超过(在我的情况下)4 个项目时,它开始发生。

GIF with 4 items

GIF with more than 4 items

当我禁用过渡动画时,卡片视图扩展可以很好地处理超过 4 个项目。我认为问题与职位变动有关,但我找不到任何解决问题的方法。

我用来实现卡片视图扩展的指南可以在这里找到: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”的库让它工作,但似乎仍然无法弄清楚为什么没有其他库它就不能工作。

【问题讨论】:

  • 考虑 TransitionManager.beginDelayedTransition(r1);TransitionManager.beginDelayedTransition();

标签: android animation position android-recyclerview


【解决方案1】:

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

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

还有myAdapter.setHasStableIds(true);

【讨论】:

    【解决方案2】:

    我遇到了同样的问题。这就是我的工作方式,就像你在GIF with 4 items 上展示的那样:)

    在您的自定义适配器中添加 notifyItemChanged(position)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);
            }
        });
    }
    

    声明全局变量mExpandedPositionmPreviousExpandedPosition并将它们初始化为-1。

    mRecyclerView 作为参数传递给适配器的构造函数。

    在为回收视图设置适配器之后,在您的片段或活动集 mRecyclerView.setItemAnimator(null) 中,如下所示:

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

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

    【讨论】:

    • 非常感谢。它确实解决了我的问题。如果 mRecyclerView.setItemAnimator(null);没有给出,默认会出现淡出...
    • ? 3 小时试图弄清楚这件事。非常感谢。
    【解决方案3】:

    我遇到了类似的问题。当屏幕外没有项目时,它可以正常工作,但是当您在屏幕外有项目时,动画无法正常工作。解决方案是不使用 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);
    
            }
        });
    

    【讨论】:

    • 呃,这花了我很长时间才找到。这个解决方案并不完美,因为更改的项目仍然会消失并重新出现,但它确实有效。恼人的是,它非常适合不在屏幕上的视图。另外,不要忘记 notifyItemChanged(oldPosition) if oldPosition != -1
    猜你喜欢
    • 2021-10-13
    • 2018-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多