Android自定义ViewGroup自动分配子view位置

来源:互联网 发布:qt socket多线程编程 编辑:程序博客网 时间:2024/05/21 19:23

子布局的view的宽高是wrap属性,功能是自动分配子view的位置, 具有自动换行,水平居中的功能

图示

图示

代码

import android.content.Context;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;import com.magus.trainingfirstapp.utils.DisplayUtil;/** * Created by yangshuai in the 17:25 of 2015.12.02 . * 自动分配子view的位置, 具有自动换行,水平居中的功能 */public class AutoDisplayChildViewContainer extends ViewGroup {    private int parentWidth;    private int totaleft = 0;    private int totalTop = 0;    private int margin = 10;    private int maxChildHeight = 0;    private int totalRight = 0;    public AutoDisplayChildViewContainer(Context context) {        super(context);    }    public AutoDisplayChildViewContainer(Context context, AttributeSet attrs) {        super(context, attrs);    }    public AutoDisplayChildViewContainer(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        /* 测量父布局 */        parentWidth = measureSize(widthMeasureSpec, DisplayUtil.dip2px(getContext(), 240));        int count = getChildCount();        int tempMaxChildHeight = 0;        int tempTotalHeight = 0;        int tempTotalRight = 0;        for (int i = 0; i < count; i++) {            View child = getChildAt(i);            if (child.getVisibility() != View.GONE) {                /* 测量子布局 */                if (child.getMeasuredWidth() > parentWidth) {                    child.measure(parentWidth, child.getMeasuredHeight());                } else                    child.measure(child.getMeasuredWidth(), child.getMeasuredHeight());                tempMaxChildHeight = Math.max(tempMaxChildHeight, child.getMeasuredHeight());                tempTotalRight += child.getMeasuredWidth();                if (tempTotalRight > parentWidth) {                    tempTotalHeight += tempMaxChildHeight;                    tempMaxChildHeight = child.getMeasuredHeight();                    tempTotalRight = child.getMeasuredWidth();                }            }        }        /* 获取适配子布局后的高度 */        int parentHeight = tempTotalHeight + tempMaxChildHeight + margin;        setMeasuredDimension(parentWidth, parentHeight);    }    private int measureSize(int measureSpec, int defaultSize) {        int mode = MeasureSpec.getMode(measureSpec);        int size = MeasureSpec.getSize(measureSpec);        int result = defaultSize;        if (mode == MeasureSpec.EXACTLY) {            result = size;        } else if (mode == MeasureSpec.AT_MOST) {            result = Math.max(size, result);        }        return result;    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        int count = getChildCount();        int lineViewCount = 0;        for (int i = 0; i < count; i++) {            View child = getChildAt(i);            if (child.getVisibility() != View.GONE) {                if (i != 0) {                    /* child 的 left 是上个子 view 的宽加上 margin */                    totaleft += getChildAt(i - 1).getMeasuredWidth() + margin;                } else {                    totaleft = 0;                    totalTop = 0;                    maxChildHeight = child.getMeasuredHeight();                }                /* child 的 right */                totalRight = totaleft + child.getMeasuredWidth();                /* 如果 rigth 大于 父布局的宽, 则换行 */                if (totalRight > parentWidth) {                    adjustLine(lineViewCount, i); // 调整这一行的子布局的位置                    lineViewCount = 0;  // 这一行的子 child 的数量充值                    totalTop += maxChildHeight;                    totaleft = 0;                    maxChildHeight = child.getMeasuredHeight();                    totalRight = child.getMeasuredWidth();                }else {                    maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight());                }                child.layout(                        totaleft,                        totalTop,                        totalRight,                        totalTop + child.getMeasuredHeight()                );                /* 统计这一行的子view的数量 */                lineViewCount++;            }        }        /* 调整最后一行子布局的位置 */        totaleft = totalRight + margin;        adjustLine(lineViewCount, count);    }    /* 调整一行,让这一行的子布局水平居中 */    private void adjustLine(int lineViewCount, int i) {        totaleft = (parentWidth - totaleft) / 2;        int marginTop;        for (int lineViewNumber = lineViewCount; lineViewNumber > 0; lineViewNumber--) {            View lineViewChild = getChildAt(i - lineViewNumber);            totalRight = totaleft + lineViewChild.getMeasuredWidth();            if (lineViewChild.getMeasuredHeight() != maxChildHeight) {                marginTop = (maxChildHeight - lineViewChild.getMeasuredHeight()) / 2;            } else {                marginTop = 0;            }            lineViewChild.layout(totaleft, totalTop + marginTop, totalRight, totalTop + marginTop + lineViewChild.getMeasuredHeight());            totaleft += lineViewChild.getMeasuredWidth() + margin;        }    }}

github

https://github.com/Afra55/TrainingFirstApp

5 0
原创粉丝点击