您的位置:首页 > 移动开发 > Android开发

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

2015-12-03 13:01 766 查看
子布局的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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: