【问题标题】:CardView not expanding on 2nd clickCardView 在第二次点击时没有展开
【发布时间】:2018-08-23 16:44:58
【问题描述】:

在为这些CardViews 实现了自定义动画后,前两个的行为并没有按照应有的方式进行。项目 A 和项目 B 在第二次点击时不会展开,但项目 C 工作正常。

public class MyRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private static final int TYPE_HEADER = 0;
    private static final int TYPE_ITEM = 1;

    private Context mContext;

    RecyclerViewHeader header;
    List<MyRecyclerViewItem> listItems;
    ValueAnimator mAnimator;



    public MyRecyclerAdapter(Context context, RecyclerViewHeader header, List<MyRecyclerViewItem> listItems)
    {
        this.mContext = context;
        this.header = header;
        this.listItems = listItems;    
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if(viewType == TYPE_HEADER)
        {
            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_header, parent, false);
            return new MyRecyclerAdapter.VHHeader(v);
        }
        else if(viewType == TYPE_ITEM)
        {
            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item, parent, false);
            return new MyRecyclerAdapter.VHItem(v);
        }
        throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");
    }

    private MyRecyclerViewItem getItem(int position)
    {
        return listItems.get(position);
    }


    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        final Typeface iconFont = FontManager.getTypeface(mContext, FontManager.FONTAWESOME);


        if (holder instanceof VHHeader)
        {
            final VHHeader vhHeader = (VHHeader)holder;                
        }
        else if (holder instanceof VHItem)
        {
            MyRecyclerViewItem currentItem = getItem(position-1);
            final VHItem vhItem = (VHItem)holder;

            vhItem.txtA.setText(currentItem.getContinent());
            vhItem.txtB.setText(currentItem.getCountry());

            vhItem.txtB.setVisibility(View.GONE);


            vhItem.txtExpandCollapse.setText(R.string.fa_icon_chevron_down);
            vhItem.txtExpandCollapse.setTypeface(iconFont);

            //Add onPreDrawListener
            vhItem.txtB.getViewTreeObserver().addOnPreDrawListener(
            new ViewTreeObserver.OnPreDrawListener() {

                @Override
                public boolean onPreDraw() {
                    vhItem.txtB.getViewTreeObserver().removeOnPreDrawListener(this);
                    vhItem.txtB.setVisibility(View.GONE);

                    final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
                    final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
                    vhItem.txtB.measure(widthSpec, heightSpec);

                    mAnimator = vhItem.slideAnimator(0, vhItem.txtB.getMeasuredHeight());
                    return true;
                }
            });

            vhItem.cardView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(vhItem.txtB.getVisibility() == View.GONE){
                        vhItem.expand();
                    } else {
                        vhItem.collapse();
                    }
                }
            });
        }
    }

    @Override
    public int getItemViewType(int position) {
        if(isPositionHeader(position))
            return TYPE_HEADER;
            return TYPE_ITEM;
    }

    private boolean isPositionHeader(int position)
    {
        return position == 0;
    }

    // increasing getItemcount to 1. This will be the row of header.
    @Override
    public int getItemCount() {
        return listItems.size()+1;
    }

    class VHHeader extends RecyclerView.ViewHolder{
        Button btnCollapseAll, btnExpandAll;

        public VHHeader(View headerView) {
            super(headerView);

            this.btnCollapseAll = headerView.findViewById(R.id.btn_collapseall);
            this.btnExpandAll = headerView.findViewById(R.id.btn_expandall);
        }
    }

    public class VHItem extends RecyclerView.ViewHolder{
        CardView cardView;
        RelativeLayout mRelativeLayout;
        TextView txtExpandCollapse, txtA, txtB;

        public VHItem(View itemView) {
            super(itemView);

            this.cardView = itemView.findViewById(R.id.cv);
            this.mRelativeLayout = itemView.findViewById(R.id.tv_rv_relativelayout);
            this.txtExpandCollapse = itemView.findViewById(R.id.tv_rv_expandcollapse);
            this.txtA = itemView.findViewById(R.id.tv_rv_A);
            this.txtB = itemView.findViewById(R.id.tv_rv_B);
        }

        private void expand() {
            // set Visible
            txtB.setVisibility(View.VISIBLE);

            // change direction of chevron to 'up'
            txtExpandCollapse.setText(R.string.fa_icon_chevron_up);

            mAnimator.start();
        }

        private void collapse() {
            // change direction of chevron to 'down'
            txtExpandCollapse.setText(R.string.fa_icon_chevron_down);

            int finalHeight = txtB.getHeight();

            ValueAnimator mAnimator = slideAnimator(finalHeight, 0);

            mAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationEnd(Animator animator) {
                    //Height=0, but it set visibility to GONE
                    txtB.setVisibility(View.GONE);
                }

                @Override
                public void onAnimationStart(Animator animator) {
                }

                @Override
                public void onAnimationCancel(Animator animator) {
                }

                @Override
                public void onAnimationRepeat(Animator animator) {
                }
            });
            mAnimator.start();
        }


        public ValueAnimator slideAnimator(int start, int end) {

            ValueAnimator animator = ValueAnimator.ofInt(start, end);


            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    //Update Height
                    int value = (Integer) valueAnimator.getAnimatedValue();

                    ViewGroup.LayoutParams layoutParams = txtB.getLayoutParams();
                    layoutParams.height = value;
                    txtB.setLayoutParams(layoutParams);
                }
            });
            return animator;
        }
    }
}

【问题讨论】:

  • 我建议在你的 cardView.onClickListener 中添加日志语句以获取每个项目的 txtB 的可见性以及项目状态的其他信息
  • 您是否尝试在开始前在展开方法上添加 mAnimator = vhItem.slideAnimator(0, txtB.getMeasuredHeight());
  • @KrishnaSharma 是的,但这不起作用
  • animator 有问题,可以试试硬编码 mAnimator =vhItem.slideAnimator(0,50); mAnimator.start()
  • @KrishnaSharma vhItem 在该方法中是不允许的。我尝试使用mAnimator = txtB.slideAnimator(0,50);,但返回了slideAnimator 的未解决方法。

标签: java android android-animation android-cardview


【解决方案1】:

你需要重新初始化mAnimator对象。

试试下面,

在VHItem类中再定义一个成员变量来保持textB的高度

public class VHItem extends RecyclerView.ViewHolder{
    CardView cardView;
    RelativeLayout mRelativeLayout;
    TextView txtExpandCollapse, txtA, txtB;
    int textBHeight; // new variable
}

然后从onPreDraw方法初始化

public boolean onPreDraw() {
    vhItem.txtB.getViewTreeObserver().removeOnPreDrawListener(this);
    vhItem.txtB.setVisibility(View.GONE);

    final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    vhItem.txtB.measure(widthSpec, heightSpec);

    vhItem.textBHeight = vhItem.txtB.getMeasuredHeight();
    return true;
}

然后在开始之前初始化animator

private void expand() {
    txtB.setVisibility(View.VISIBLE);
    txtExpandCollapse.setText(R.string.fa_icon_chevron_up);
    mAnimator = slideAnimator(0,textBHeight); 
    mAnimator.start();
}

【讨论】:

    【解决方案2】:

    将对象 CardView 更改为 View。

    尝试在内部类 VHItem 上执行以下操作,而不是在 cardview 上生成事件:

    View view;
    RelativeLayout mRelativeLayout;
    TextView txtExpandCollapse, txtA, txtB;
    
    public VHItem(View itemView) {
       super(itemView);
    
       this.view = itemView;
       this.mRelativeLayout = itemView.findViewById(R.id.tv_rv_relativelayout);
       this.txtExpandCollapse = itemView.findViewById(R.id.tv_rv_expandcollapse);
       this.txtA = itemView.findViewById(R.id.tv_rv_A);
       this.txtB = itemView.findViewById(R.id.tv_rv_B);
    

    }

    现在,关于 onBindViewHolder 方法:

    vhItem.view.setOnClickListener(new View.OnClickListener() {

      @Override
      public void onClick(View v) {
    
         if(vhItem.txtB.getVisibility() == View.GONE){
            vhItem.expand();
         } else {
            vhItem.collapse();
         }
     }
    

    });

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-28
      • 1970-01-01
      • 2015-02-28
      • 2022-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多