源码来自 http://blog.csdn.net/lmj623565791/article/details/38339817
升级代码 http://blog.csdn.net/lmj623565791/article/details/38352503 实现FlowLayout
主要是 onMeasure 和 onLayout 的运用
package com.weidingqiang.testviewb; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; /** * Created by weidingqiang on 15/11/19. */ public class BaViewGroup extends ViewGroup { public BaViewGroup(Context context) { this(context,null); } public BaViewGroup(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { /** * 获得此ViewGroup上级容器为其推荐的宽和高,以及计算模式 */ int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int sizeWidth = MeasureSpec.getSize(widthMeasureSpec); int sizeHeight = MeasureSpec.getSize(heightMeasureSpec); // 计算出所有的childView的宽和高 measureChildren(widthMeasureSpec, heightMeasureSpec); /** * 记录如果是wrap_content是设置的宽和高 */ int width = 0; int height = 0; int cCount = getChildCount(); int cWidth = 0; int cHeight = 0; MarginLayoutParams cParams = null; // 用于计算左边两个childView的高度 int lHeight = 0; // 用于计算右边两个childView的高度,最终高度取二者之间大值 int rHeight = 0; // 用于计算上边两个childView的宽度 int tWidth = 0; // 用于计算下面两个childiew的宽度,最终宽度取二者之间大值 int bWidth = 0; /** * 根据childView计算的出的宽和高,以及设置的margin计算容器的宽和高,主要用于容器是warp_content时 */ for (int i = 0; i < cCount; i++) { View childView = getChildAt(i); cWidth = childView.getMeasuredWidth(); cHeight = childView.getMeasuredHeight(); cParams = (MarginLayoutParams) childView.getLayoutParams(); // 上面两个childView if (i == 0 || i == 1) { tWidth += cWidth + cParams.leftMargin + cParams.rightMargin; } if (i == 2 || i == 3) { bWidth += cWidth + cParams.leftMargin + cParams.rightMargin; } if (i == 0 || i == 2) { lHeight += cHeight + cParams.topMargin + cParams.bottomMargin; } if (i == 1 || i == 3) { rHeight += cHeight + cParams.topMargin + cParams.bottomMargin; } } width = Math.max(tWidth, bWidth); height = Math.max(lHeight, rHeight); /** * 如果是wrap_content设置为我们计算的值 * 否则:直接设置为父容器计算的值 */ setMeasuredDimension((widthMode == MeasureSpec.EXACTLY) ? sizeWidth : width, (heightMode == MeasureSpec.EXACTLY) ? sizeHeight : height); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int cCount = getChildCount(); int cWidth = 0; int cHeight = 0; MarginLayoutParams cParams = null; /** * 遍历所有childView根据其宽和高,以及margin进行布局 */ for (int i = 0; i < cCount; i++) { View childView = getChildAt(i); cWidth = childView.getMeasuredWidth(); cHeight = childView.getMeasuredHeight(); cParams = (MarginLayoutParams) childView.getLayoutParams(); int cl = 0, ct = 0, cr = 0, cb = 0; switch (i) { case 0: cl = cParams.leftMargin; ct = cParams.topMargin; break; case 1: cl = getWidth() - cWidth - cParams.leftMargin - cParams.rightMargin; ct = cParams.topMargin; break; case 2: cl = cParams.leftMargin; ct = getHeight() - cHeight - cParams.bottomMargin; break; case 3: cl = getWidth() - cWidth - cParams.leftMargin - cParams.rightMargin; ct = getHeight() - cHeight - cParams.bottomMargin; break; } cr = cl + cWidth; cb = cHeight + ct; childView.layout(cl, ct, cr, cb); } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); } @Override public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); } }
布局文件
<com.weidingqiang.testviewb.BaViewGroup android:layout_width="300dp" android:layout_height="300dp" android:background="#ff0" > <TextView android:layout_width="50dp" android:layout_height="50dp" android:background="#FF4444" android:gravity="center" android:text="0" android:textColor="#FFFFFF" android:textSize="22sp" android:textStyle="bold" /> <TextView android:layout_width="50dp" android:layout_height="50dp" android:background="#00ff00" android:gravity="center" android:text="1" android:textColor="#FFFFFF" android:textSize="22sp" android:textStyle="bold" /> <TextView android:layout_width="50dp" android:layout_height="50dp" android:background="#ff0000" android:gravity="center" android:text="2" android:textColor="#FFFFFF" android:textSize="22sp" android:textStyle="bold" /> <TextView android:layout_width="50dp" android:layout_height="50dp" android:background="#0000ff" android:gravity="center" android:text="3" android:textColor="#FFFFFF" android:textSize="22sp" android:textStyle="bold" /> </com.weidingqiang.testviewb.BaViewGroup>
原文:http://www.cnblogs.com/weidingqiang/p/4979887.html