Android自定义控件 - 标签流式布局
很简单,先看效果:

思路:
重写onMeasure计算childView宽度,如果当前ChildView放不下当前行,那么当前行剩余的空间由当前行其它控件平分,当前childView放入下一行,如果childView大于父View宽度,那么childView.width=ViewGroup.width。(如果子控件为GONE则不测量)
重写onMeasure (代码有点粗糙^_^):
@Override PRotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int childCount = getChildCount(); int measuredWidth = MeasureSpec.getSize(widthMeasureSpec); int currentWith = 0, visNum = 0; int key = 0; for (int i = 0; i < childCount; i++) { View childAt = getChildAt(i); if (childAt.getVisibility() == GONE) { key++; visNum++; continue; } childAt.measure(0, 0); int redWidth = childAt.getMeasuredWidth(); if (redWidth + currentWith > getMeasuredWidth()) { int avgWidth = key < 1 ? 0 : (measuredWidth - currentWith) / (key - visNum); for (; key > 0; key--) { View childView = getChildAt(i - key); if (childView.getVisibility() == GONE) continue; int redWidth1 = childView.getMeasuredWidth(); int redHeight1 = childView.getMeasuredHeight(); redWidth1 += avgWidth; int childMeasureWidth = MeasureSpec.makeMeasureSpec(redWidth1, MeasureSpec.EXACTLY); int childMeasureHeight = MeasureSpec.makeMeasureSpec(redHeight1, MeasureSpec.EXACTLY); childView.measure(childMeasureWidth, childMeasureHeight); } currentWith = 0; key = 0; visNum = 0; } key++; currentWith += redWidth; } }重写onLayout:@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int childCount = getChildCount(); int currentWidth = 0, currentHeight = 0, maxHeight = 0; for (int i = 0; i < childCount; i++) { View childAt = getChildAt(i); if (childAt.getVisibility() == GONE) continue; int redWidth = childAt.getMeasuredWidth(); int redHeight = childAt.getMeasuredHeight(); maxHeight = redHeight > maxHeight ? redHeight : maxHeight; if (currentWidth + redWidth > r && currentWidth>0) { currentWidth = 0; currentHeight += maxHeight; maxHeight = 0; } redWidth = redWidth > (r - currentWidth) ? r - currentWidth : redWidth; setLayout(childAt, currentWidth, currentHeight, redWidth, redHeight); currentWidth += redWidth; } }完整代码:
import android.content.Context;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;public class MyStreamLayout extends ViewGroup { public MyStreamLayout(Context context) { super(context); } public MyStreamLayout(Context context, AttributeSet attrs) { super(context, attrs); } public MyStreamLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } void setLayout(View v, int x, int y, int w, int h) { v.layout(x, y, w + x, h + y); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int childCount = getChildCount(); int measuredWidth = MeasureSpec.getSize(widthMeasureSpec); int currentWith = 0, visNum = 0; int key = 0; for (int i = 0; i < childCount; i++) { View childAt = getChildAt(i); if (childAt.getVisibility() == GONE) { key++; visNum++; continue; } childAt.measure(0, 0); int redWidth = childAt.getMeasuredWidth(); if (redWidth + currentWith > getMeasuredWidth()) { int avgWidth = key < 1 ? 0 : (measuredWidth - currentWith) / (key - visNum); for (; key > 0; key--) { View childView = getChildAt(i - key); if (childView.getVisibility() == GONE) continue; int redWidth1 = childView.getMeasuredWidth(); int redHeight1 = childView.getMeasuredHeight(); redWidth1 += avgWidth; int childMeasureWidth = MeasureSpec.makeMeasureSpec(redWidth1, MeasureSpec.EXACTLY); int childMeasureHeight = MeasureSpec.makeMeasureSpec(redHeight1, MeasureSpec.EXACTLY); childView.measure(childMeasureWidth, childMeasureHeight); } currentWith = 0; key = 0; visNum = 0; } key++; currentWith += redWidth; } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int childCount = getChildCount(); int currentWidth = 0, currentHeight = 0, maxHeight = 0; for (int i = 0; i < childCount; i++) { View childAt = getChildAt(i); if (childAt.getVisibility() == GONE) continue; int redWidth = childAt.getMeasuredWidth(); int redHeight = childAt.getMeasuredHeight(); maxHeight = redHeight > maxHeight ? redHeight : maxHeight; if (currentWidth + redWidth > r && currentWidth > 0) { currentWidth = 0; currentHeight += maxHeight; maxHeight = 0; } redWidth = redWidth > (r - currentWidth) ? r - currentWidth : redWidth; setLayout(childAt, currentWidth, currentHeight, redWidth, redHeight); currentWidth += redWidth; } }}使用:<com.example.demo.MyStreamLayout android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="ChildView" /> </com.example.demo.MyStreamLayout>
新闻热点
疑难解答