Android实际开发问题08------自动换行容器

设计思路:onmeasure时设置子控件大小自适应,onLayout时设置子控件位置

public class WrapLayout extends ViewGroup {


    //横向间隔
    private int horizontalSpacing;

    //纵向间隔
    private int verticalSpacing;

    public WrapLayout(Context context) {
        super(context);
    }

    public WrapLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs, 0);
    }

    public WrapLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs, defStyleAttr);
    }

    /**
     * 初始化
     *
     * @param attrs
     * @param defStyleAttr
     */
    private void init(AttributeSet attrs, int defStyleAttr) {
        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.WrapLayout, defStyleAttr, 0);
        horizontalSpacing = typedArray.getInt(R.styleable.WrapLayout_horizontalSpacing, 0);
        horizontalSpacing = pxFromDp(horizontalSpacing);
        verticalSpacing = typedArray.getInt(R.styleable.WrapLayout_verticalSpacing, 0);
        verticalSpacing = pxFromDp(verticalSpacing);
    }

    @Override
    protected void onLayout(boolean b, int left, int top, int right, int bottom) {

        if (b) {
            //获取容器宽度
            int width = right - left;
            //获取左内边距
            int paddingLeft = getPaddingLeft();
            //获取上内边距
            int paddingTop = getPaddingTop();
            //获取右内边距
            int paddingRight = getPaddingRight();
            //设置初始点位的x坐标为左内边距
            int x = paddingLeft;
            //设置初始点位的y坐标为上内边距
            int y = paddingTop;
            //设置下一行高度坐标
            int maxHeight = paddingTop;
            //获取子控件个数
            int count = getChildCount();
            for (int i = 0; i < count; i++) {
                View childView = getChildAt(i);
                int measuredHeight = childView.getMeasuredHeight();
                int measuredWidth = childView.getMeasuredWidth();
                //超过一行宽度后需要换行
                if (x + measuredWidth + paddingRight > width) {
                    y = maxHeight;
                    x = paddingLeft;
                }
                //获取下一行的起始点
                maxHeight = Math.max(y + measuredHeight + verticalSpacing, maxHeight);
                //设置子view的位置
                childView.layout(x, y, x + measuredWidth, y + measuredHeight);
                //设置下一个子view的宽度起点x坐标
                x = x + measuredWidth + horizontalSpacing;
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //获取子控件个数
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            //获取子控件
            View view = getChildAt(i);
            //设置子控件大小为自适应
            view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }


    private int dpFromPx(final float px) {
        return (int) (px / getResources().getDisplayMetrics().density);
    }

    private int pxFromDp(final float dp) {
        return (int) (dp * getResources().getDisplayMetrics().density);
    }

}


控件属性

<resources>
    <declare-styleable name="WrapLayout">
        <attr name="verticalSpacing" format="integer"/>
        <attr name="horizontalSpacing" format="integer"/>
    </declare-styleable>
</resources>

你可能感兴趣的:(Android实际开发问题08------自动换行容器)