流布局Flowlayoiut

直接上代码:

 1 ViewGroup 的使用

/**
 * 个人理解,容器的布局执行过程 1 父容器调用measureChildren 2 子容器调用measure 计算当前容器的宽高和其子容器的宽高 3
 * 当前执行的这个子容器触发onMeasure ,设置当前子容器的宽高 4 当前容器调用onLayout , 来展示当前容器的显示
 */
public class CustomFlowlayoutContainer extends ViewGroup {

	public CustomFlowlayoutContainer(Context context) {
		super(context);
	}

	// attrs 是xml中配置的参数会传到这里
	public CustomFlowlayoutContainer(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
		return new MarginLayoutParams(getContext(), attrs);
	}

	/**
	 * 
	 * 根据父类传入的 widthMeasureSpec和heightMeasureSpec计算本类和其子类的宽高
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

		// 获得它的父容器为它设置的测量模式和大小
		int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);//容器的模式为fill_parent或者固定大小,所以这个值为容器宽度
		int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
		int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
		int modeHeight = MeasureSpec.getMode(heightMeasureSpec);

		// 如果是warp_content情况下,记录宽和高
		int width = 0;
		int height = 0;
		/**
		 * 记录每一行的宽度,width不断取最大宽度
		 */
		int lineWidth = 0;
		/**
		 * 每一行的高度,累加至height
		 */
		int lineHeight = 0;

		int cCount = getChildCount();

		// 遍历每个子元素
		for (int i = 0; i < cCount; i++) {
			View child = getChildAt(i);
			// 测量每一个child的宽和高
			measureChild(child, widthMeasureSpec, heightMeasureSpec);
			// 得到child的lp
			MarginLayoutParams lp = (MarginLayoutParams) child
					.getLayoutParams();
			// 当前子控件实际占据的宽度
			int childWidth = child.getMeasuredWidth() + lp.leftMargin
					+ lp.rightMargin;
			// 当前子控件实际占据的高度
			int childHeight = child.getMeasuredHeight() + lp.topMargin
					+ lp.bottomMargin;
			/**
			 * 如果加入当前child,则超出最大宽度,则的到目前最大宽度给width,类加height 然后开启新行
			 */
			if (lineWidth + childWidth > sizeWidth) {
				width = Math.max(lineWidth, childWidth);// 取最大的
				lineWidth = childWidth; // 重新开启新行,开始记录
				// 叠加当前高度,
				height += lineHeight;
				// 开启记录下一行的高度
				lineHeight = childHeight;
			} else
			// 否则累加值lineWidth,lineHeight取最大高度
			{
				lineWidth += childWidth;
				lineHeight = Math.max(lineHeight, childHeight);
			}
			// 如果是最后一个,则将当前记录的最大宽度和当前lineWidth做比较
			if (i == cCount - 1) {
				width = Math.max(width, lineWidth);
				height += lineHeight;
			}

		}
		//一般流式布局宽为EXACTLY所以数值为sizeWidth,高为wrap_content 为计算的height
		setMeasuredDimension((modeWidth == MeasureSpec.EXACTLY) ? sizeWidth
				: width, (modeHeight == MeasureSpec.EXACTLY) ? sizeHeight
				: height);

	}

	/** 
     * 存储所有的View,按行记录 
     */  
    private List<List<View>> mAllViews = new ArrayList<List<View>>();  
    /** 
     * 记录每一行的最大高度 
     */  
    private List<Integer> mLineHeight = new ArrayList<Integer>();  
    
	/**
	 * 对其所有childView进行定位
	 */
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		//每次布局前要清零
	    mAllViews.clear();  
        mLineHeight.clear();  
  
        int width = getWidth();  
        
        int lineWidth = 0;  
        int lineHeight = 0;  
        // 存储每一行所有的childView  
        List<View> lineViews = new ArrayList<View>(); 
 
		int cCount = getChildCount();
	    // 遍历所有的孩子  
        for (int i = 0; i < cCount; i++)  
        {  
            View child = getChildAt(i);  
            MarginLayoutParams lp = (MarginLayoutParams) child  
                    .getLayoutParams();  
            int childWidth = child.getMeasuredWidth();  
            int childHeight = child.getMeasuredHeight();  
  
            // 如果已经需要换行  
            if (childWidth + lp.leftMargin + lp.rightMargin + lineWidth > width)  
            {  
                // 记录这一行所有的View以及最大高度  
                mLineHeight.add(lineHeight);  
                // 将当前行的childView保存,然后开启新的ArrayList保存下一行的childView  
                mAllViews.add(lineViews);  
                lineWidth = 0;// 重置行宽  
                lineViews = new ArrayList<View>();  
            }  
            /** 
             * 如果不需要换行,则累加 
             */  
            lineWidth += childWidth + lp.leftMargin + lp.rightMargin;  
            lineHeight = Math.max(lineHeight, childHeight + lp.topMargin  
                    + lp.bottomMargin);  
            lineViews.add(child);  
        }  
        // 记录最后一行  
        mLineHeight.add(lineHeight);  
        mAllViews.add(lineViews);  
  
        int left = 0;  
        int top = 0;  
        // 得到总行数  
        int lineNums = mAllViews.size();  
        for (int i = 0; i < lineNums; i++)  
        {  
            // 每一行的所有的views  
            lineViews = mAllViews.get(i);  
            // 当前行的最大高度  
            lineHeight = mLineHeight.get(i);  
  
            Log.e("位置", "第" + i + "行 :" + lineViews.size() + " , " + lineViews);  
            Log.e("位置", "第" + i + "行, :" + lineHeight);  
  
            // 遍历当前行所有的View  
            for (int j = 0; j < lineViews.size(); j++)  
            {  
                View child = lineViews.get(j);  
                if (child.getVisibility() == View.GONE)  
                {  
                    continue;  
                }  
                MarginLayoutParams lp = (MarginLayoutParams) child  
                        .getLayoutParams();  
  
                //计算childView的left,top,right,bottom  
                int lc = left + lp.leftMargin;  
                int tc = top + lp.topMargin;  
                int rc =lc + child.getMeasuredWidth();  
                int bc = tc + child.getMeasuredHeight();  
  
                Log.e("位置", child + " , l = " + lc + " , t = " + t + " , r ="  
                        + rc + " , b = " + bc);  
  
                child.layout(lc, tc, rc, bc);  
                  
                left += child.getMeasuredWidth() + lp.rightMargin  
                        + lp.leftMargin;  
            }  
            left = 0;  
            top += lineHeight;  
        }  
	}
}

 2 Activity代码

public class TestFlowlayoutActivity extends Activity implements OnClickListener {
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_flowlayout );
		//DisplayUtil displayUtil = new DisplayUtil(getWindowManager());
	}
	@Override
	public void onClick(View v) {

		switch (v.getId()) {
		case R.id.start:
		 
			break;
		default:
			break;
		}
	}
}

 3 xml 代码

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    android:background="#E1E6F6"  
    android:orientation="vertical" >  
  
    <com.example.fragmentdemo1.widget.CustomFlowlayoutContainer
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content" >  
  
        <TextView  
           	android:layout_width="wrap_content"
           	android:layout_height="wrap_content"
           	android:layout_margin="4dp"
           	android:background="@drawable/button_bg"
            android:text="Welcome" />  
  
        <TextView  
           	android:layout_width="wrap_content"
           	android:layout_height="wrap_content"
           	android:layout_margin="4dp"
           	android:background="@drawable/button_bg"
            android:text="IT工程师" />  
  
        <TextView  
           	android:layout_width="wrap_content"
           	android:layout_height="wrap_content"
           	android:layout_margin="4dp"
           	android:background="@drawable/button_bg"
            android:text="努力啊" />  
  
        <TextView  
           	android:layout_width="wrap_content"
           	android:layout_height="wrap_content"
           	android:layout_margin="4dp" 
           	android:background="@drawable/button_bg"
            android:text="学习挣钱" />  
  
        <TextView  
           	android:layout_width="wrap_content"
           	android:layout_height="wrap_content"
           	android:layout_margin="4dp" 
           	android:background="@drawable/button_bg"
            android:text="攒钱娶媳妇了" />  
  
        <TextView  
           	android:layout_width="wrap_content"
           	android:layout_height="wrap_content"
           	android:layout_margin="4dp" 
           	android:background="@drawable/button_bg"
            android:text="攒钱买房子了" />  
  
        <TextView  
           	android:layout_width="wrap_content"
           	android:layout_height="wrap_content"
           	android:layout_margin="4dp"
           	android:background="@drawable/button_bg"
            android:text="攒钱买车子了,什么时候出去玩玩" />  
        <TextView  
           	android:layout_width="wrap_content"
           	android:layout_height="wrap_content"
           	android:layout_margin="4dp"
           	android:background="@drawable/button_bg"
            android:text="一辈子就这样没了,该出去休息一下了" />
        
    </com.example.fragmentdemo1.widget.CustomFlowlayoutContainer>  
      
    </LinearLayout>

 4 背景代码button_bg.xml

  

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >  
  	<!-- 填充色 -->
    <solid android:color="#FFFFFF" >  
    </solid>  
  	<!-- 圆角 -->
    <corners android:radius="20dp"/>  
    <!-- 描边 -->
    <stroke android:color="#C9C9C9" android:width="2dp"/>  
      
    <padding  
        android:bottom="2dp"  
        android:left="10dp"  
        android:right="10dp"  
        android:top="2dp" />  
  
</shape>

相关推荐