CardView在第二次点击时无法展开

时间:2018-08-23 16:44:58

标签: java android android-animation android-cardview

在为这CardView个实现自定义动画之后,前两个没有按照应有的方式运行。项目A和项目B不会在第二次点击时展开,但项目C可以很好地工作。

enter image description here

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;
        }
    }
}

2 个答案:

答案 0 :(得分:2)

您需要重新初始化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;
}

然后在开始之前初始化动画制作器

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

答案 1 :(得分:0)

将对象CardView更改为View。

与其在cardview上生成事件,不如对内部类VHItem执行以下操作:

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();
     }
 }

});