自定義控制元件---類似新增郵件收件人效果
阿新 • • 發佈:2019-02-07
自定義控制元件:增加控制元件時會則適應高度,寬度不夠時會跳至下一行;無焦點可以控制高度,有焦點顯示最大高度。
直接上程式碼:
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; } }