android 卡片式折叠展开自定义view

标签: android  自定义view

先看效果图:

实现思路:

1.外层是一个自定义的 FrameLayout,通过重写 onMeasure() 和 onLayout() 方法,动态计算其内部子view展开和折叠时的高度。

2.内部子 view 是一个自定义的 CardView(可以方便的处理圆角和阴影)。

核心代码:

其实现主要是由两个方法: onMeasure() 和 onLayout(), onMeasure() 计算布局需要的总高度(未进行宽度处理),onLayout() 进行内部子view的摆放,具体实现如下:

 外部自定义 FrameLayout 的  onMeasure() :

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (getChildCount() < 1) {
            return;
        }
        CollapsibleCardView collapsibleCardView = ((CollapsibleCardView) getChildAt(getChildCount() - 1));
        // compute height.
        final LayoutParams lp = (LayoutParams) collapsibleCardView.getLayoutParams();
        int marginTop = lp.topMargin;
        int marginBottom = lp.bottomMargin;
        int paddingTop = getPaddingTop();
        int paddingBottom = getPaddingBottom();
        int mHeaderViewHeight = collapsibleCardView.getViewHeader().getMeasuredHeight();
        int mContentViewHeight = collapsibleCardView.getViewContent().getMeasuredHeight();
        int totalHeight = paddingTop + marginTop
                + mHeaderViewHeight * (getChildCount() - 1)
                + collapsibleCardView.getMeasuredHeight()
                + paddingBottom + marginBottom;

        if (hasExpandView()) {
            totalHeight -= collapsibleCardView.getViewHeader().getMeasuredHeight();
            totalHeight += collapsibleCardView.getMeasuredHeight() + dp2px(cardStackViewSpacing);
        }
        setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), totalHeight);
    }

 外部自定义 FrameLayout 的  onLayout() :

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if (getChildCount() < 1) {
            return;
        }
        CollapsibleCardView collapsibleCardView = (CollapsibleCardView) getChildAt(0);
        final LayoutParams lp = (LayoutParams) collapsibleCardView.getLayoutParams();
        int marginStart = lp.getMarginStart();
        int marginTop = lp.topMargin;
        int childLeft = getPaddingLeft();
        int childTop = getPaddingTop();
        for (int i = 0; i < getChildCount(); i++) {
            CollapsibleCardView child = (CollapsibleCardView) getChildAt(i);
            final int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();
            child.layout(childLeft + marginStart,
                    childTop + marginTop,
                    childLeft + marginStart + childWidth,
                    childTop + marginTop + childHeight);
            if (child.isExpand()) {
                childTop += childHeight + dp2px(cardStackViewSpacing);
            } else {
                childTop += child.getViewHeader().getMeasuredHeight();
            }
        }
    }

待完善事项:

1.当布局过高时,需要在外部再添加 NestedScrollView 包裹(这个应该可以封装起来的)。

2.内部子view展开折叠没有动画效果可以配置

3.内部子view展开折叠被遮挡的时候需要外部 NestedScrollView 进行滚动处理。

具体代码 demo 地址:https://github.com/QQQQQQY/CardStackView

版权声明:本文为qq_31872881原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_31872881/article/details/105727616