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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章