自定义控件:增加控件时会则适应高度,宽度不够时会跳至下一行;无焦点可以控制高度,有焦点显示最大高度。
直接上代码:
public class LineWrapViewGroup extends ViewGroup {
private int lineHeight = 0;
private int hSpacing = 0;
private int vSpacing = 0;
public LineWrapViewGroup(Context context) {
super(context);
init(context, null, 0);
}
public LineWrapViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public LineWrapViewGroup(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LineWrapViewGroup);
// 得到横向间隔
hSpacing = a.getDimensionPixelSize(R.styleable.LineWrapViewGroup_horizontal_spacing, 5);
// 得到纵向间隔
vSpacing = a.getDimensionPixelSize(R.styleable.LineWrapViewGroup_vertical_spacing, 5);
a.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec) + getPaddingBottom() + getPaddingTop();
int xPos = getPaddingLeft();
int yPos = getPaddingTop();
int lineHeight = 0;
for (int index = 0; index < getChildCount(); index++) {
final View child = getChildAt(index);
LayoutParams lp = child.getLayoutParams();
// 算出子View宽的MeasureSpec值
int wSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.AT_MOST);
// 算出子View高的MeasureSpec值
int hSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.AT_MOST);
// measure
child.measure(wSpec, hSpec);
int childW = child.getMeasuredWidth();
int childH = child.getMeasuredHeight();
lineHeight = Math.max(lineHeight, childH + vSpacing);
if (xPos + childW > width) {
xPos = getPaddingLeft();
yPos += lineHeight;
}
xPos += childW + hSpacing;
}
this.lineHeight = lineHeight;
// 对高度期望值没有限制
/*
* 计数,两次更新后显示两个
*/
if (index < 2) {
height = yPos + lineHeight;
appointHeight = height;
} else {
height = appointHeight;
}
/*
* 控制高度
*/
if (height > heightCount) {
index++;
} else if (yPos + lineHeight < height) {
index--;
} else if (height == 0) {
index = 0;
}
heightCount = yPos + lineHeight;
if (settingHeight) {
height = appointHeight;
} else {
height = heightCount;
}
// 设置ViewGroup宽高值
setMeasuredDimension(width, height);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int count = getChildCount();
final int width = r - l;
int xpos = getPaddingLeft();
int ypos = getPaddingTop();
// 设置每一个子View的位置,左上角xy坐标与右下角xy坐标确定View的位置
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
final int childw = child.getMeasuredWidth();
final int childh = child.getMeasuredHeight();
if (xpos + childw > width) {
xpos = getPaddingLeft();
ypos += lineHeight;
}
child.layout(xpos, ypos, xpos + childw, ypos + childh);
xpos += childw + hSpacing;
}
}
}
private int index = 0; // 两行
private int appointHeight = 0; // 指定高度
private int heightCount = 0; // 最大高度
private boolean settingHeight = false; // 控制高度
/**
* 设置最大高度
*/
public void getViewHeight() {
settingHeight = false;
}
/**
* 回复为原有高度
*/
public void getOriginalHeight() {
settingHeight = true;
}
}