Android UI:自定义控件:可换行的布局控件:代码实现

ShifterLayout:子控件的宽度不固定

/**
 * 可以换行的布局控件,其中的子控件宽度不固定
 */
public class ShifterLayout extends ViewGroup {
    public ShifterLayout(Context context) {
        super(context);
    }


    public ShifterLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childTop = this.getPaddingTop();
        int childLeft = this.getPaddingLeft();
        int childWidth = 0;
        int childHeight  = 0;
        int tempChildLeft = 0;
        for(int i=0; i<getChildCount(); i++) {
            View child = getChildAt(i);
            if(child.getVisibility() == VISIBLE) {
                MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
                childWidth = child.getMeasuredWidth();
                childHeight  = child.getMeasuredHeight();
                //换行
                tempChildLeft = childLeft +lp.leftMargin + childWidth;
                if(tempChildLeft >= getMeasuredWidth()) {
                    childLeft = this.getPaddingLeft();
                    childTop += childHeight + lp.bottomMargin+lp.topMargin;
                }
                //
                child.layout(childLeft , childTop,
                        childLeft+childWidth, childTop+ childHeight);
                childLeft += childWidth+lp.rightMargin+lp.leftMargin;
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int childTop = this.getPaddingTop();
        int childLeft = this.getPaddingLeft();
        int childWidth = 0;
        int childHeight  = 0;
        int height = 0;
        int tempChildLeft = 0;

        int width = MeasureSpec.getSize(widthMeasureSpec);
        for(int i=0; i<getChildCount(); i++) {
            View child = this.getChildAt(i);
            if(child.getVisibility() == VISIBLE) {
                MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
                measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
                childWidth = child.getMeasuredWidth();
                childHeight  = child.getMeasuredHeight();
                //换行
                tempChildLeft = childLeft +lp.leftMargin + childWidth;
                if(tempChildLeft >= width) {
                    childLeft = this.getPaddingLeft();
                    childTop += childHeight + lp.bottomMargin+lp.topMargin;
                }
                childLeft += childWidth+lp.rightMargin+lp.leftMargin;
             }

        }
        height = childTop + childHeight + this.getPaddingBottom();
        setMeasuredDimension(width, height);

    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }
}

ShifterLayout2:子控件的宽度一致且固定

/**
 * 可以换行的布局控件,其中的子控件宽度相同且固定
 */
public class ShifterLayout2 extends ViewGroup {
    private int childWidth, childHeight;
    public ShifterLayout2(Context context) {
        super(context);
    }

    public ShifterLayout2(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
//        super.onLayout(changed, l, t, r, b);
        int childTop = this.getPaddingTop();
        int childLeft = this.getPaddingLeft();
        int tempChildLeft = 0;
        for(int i=0; i<getChildCount(); i++) {
            View child = getChildAt(i);
            if(child.getVisibility() == VISIBLE) {
                MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
                //换行
                tempChildLeft = childLeft +lp.leftMargin + childWidth;
                if(tempChildLeft >= getMeasuredWidth()) {
                    childLeft = this.getPaddingLeft();
                    childTop += childHeight + lp.bottomMargin+lp.topMargin;
                }
                //
                child.layout(childLeft , childTop,
                        childLeft+childWidth, childTop+ childHeight);
                childLeft += childWidth+lp.rightMargin+lp.leftMargin;
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        View childView = getChildAt(0);
        int measureWidth = MeasureSpec.getSize(widthMeasureSpec);
        //其他类想要获取布局控件中的子控件的宽高:布局控件.getChildAt(0).getMeasuredWidth/Height()
        //不measure其他子控件,目前没有遇到问题
        measureChildWithMargins(childView, widthMeasureSpec, 0, heightMeasureSpec, 0);
//        for(int i=0; i<getChildCount(); i++) {
//            View child = getChildAt(i);
//            measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
//        }
        MarginLayoutParams lp =
                (MarginLayoutParams) childView.getLayoutParams();
        int childLeftMargin = lp.leftMargin;
        int childTopMargin = lp.topMargin;
        int childBottomMargin = lp.bottomMargin;
        childWidth = childView.getMeasuredWidth();
        childHeight = childView.getMeasuredHeight();
        int childWidth2 = childWidth + childLeftMargin;
        int childHeight2 = childHeight + childTopMargin + childBottomMargin;;
        int columnNum = (measureWidth)/(childWidth2);
        int height = 0;
        int childCount = getChildCount();
        if(childCount<columnNum) {
            height = childHeight2;
        }
        else {
            height += (childCount/columnNum)*childHeight2;
            if(childCount%columnNum != 0) {
                height += childHeight2;
            }
        }
        height -= childBottomMargin;
        setMeasuredDimension(measureWidth, height);

    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }
}

​​​​​​​

  • 25
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值