自定义控件:增加控件时会则适应高度,宽度不够时会跳至下一行;无焦点可以控制高度,有焦点显示最大高度。
直接上代码:
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; } }