First, FlowLayout introduction

FlowLayout is a control that automatically adds to the right according to the width of the ViewGroup. If the current row has insufficient space, it automatically adds to the next row. Kind of like all the controls float to the left, the first row is full, float to the second row. Android does not provide streaming layout, but it is useful in some situations, such as keyword tags, search lists, etc., as shown below: \

\

 

Two, production analysis

For FlowLayout, we need to specify the LayoutParams, we currently only need to be able to recognize margin, that is, use MarginLayoutParams.

2. OnMeasure calculates the width and height of all ChildViews and then calculates its own width and height based on the width and height of the childView. (Of course, if it’s not wrAP_content, just use the calculated value passed in by the parent ViewGroup.)

3. Layout all childViews in onLayout.

\

			// If lineWidth + chilWidth > viewGroup Max width, childView is moved to the next line
			if(lineWidth + childWidth >  widthSpec){/ / a newline
				height += lineheight;
				width = Math.max(lineWidth, childWidth);
				lineWidth = childWidth;// The next line is entered
			}else {// For the same line, the width increases
				lineWidth = lineWidth + childWidth;
				// Determine the maximum height of a row
				lineheight = Math.max(childHeight, lineheight);
			}
Copy the code



\

\

\

\

\

\

\

match_parent  android:layout_width=”fill_parent”

<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.viewgroupdemo.MyViewGroup
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

        <TextView
            style="@style/text_flag_01"
            android:text="Welcome" />

        <TextView
            style="@style/text_flag_01"
            android:text="IT engineer" />

        <TextView
            style="@style/text_flag_01"
            android:text="Learn ing" />

        <TextView
            style="@style/text_flag_01"
            android:text="The love ing" />

        <TextView
            style="@style/text_flag_01"
            android:text="Money ing" />

        <TextView
            style="@style/text_flag_01"
            android:text="Hard" ing" />

        <TextView
            style="@style/text_flag_01"
            android:text="I thick i can" />
    </com.example.viewgroupdemo.MyViewGroup>

    <com.example.viewgroupdemo.MyViewGroup
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp" >

        <TextView
            style="@style/text_flag_01"
            android:background="@drawable/flag_02"
            android:text="Welcome"
            android:textColor="# 888888" />

        <TextView
            style="@style/text_flag_01"
            android:background="@drawable/flag_02"
            android:text="IT engineer"
            android:textColor="# 888888" />

        <TextView
            style="@style/text_flag_01"
            android:background="@drawable/flag_02"
            android:text="Learn ing"
            android:textColor="# 888888" />

        <TextView
            style="@style/text_flag_01"
            android:background="@drawable/flag_02"
            android:text="The love ing"
            android:textColor="# 888888" />

        <TextView
            style="@style/text_flag_01"
            android:background="@drawable/flag_02"
            android:text="Money ing"
            android:textColor="# 888888" />

        <TextView
            style="@style/text_flag_01"
            android:background="@drawable/flag_02"
            android:text="Hard" ing"
            android:textColor="# 888888" />

        <TextView
            style="@style/text_flag_01"
            android:background="@drawable/flag_02"
            android:text="I thick i can"
            android:textColor="# 888888" />
    </com.example.viewgroupdemo.MyViewGroup>

    <com.example.viewgroupdemo.MyViewGroup
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp" >

        <TextView
            style="@style/text_flag_01"
            android:background="@drawable/flag_03"
            android:text="Welcome"
            android:textColor="#43BBE7" />

        <TextView
            style="@style/text_flag_01"
            android:background="@drawable/flag_03"
            android:text="IT engineer"
            android:textColor="#43BBE7" />

        <TextView
            style="@style/text_flag_01"
            android:background="@drawable/flag_03"
            android:text="Learn ing"
            android:textColor="#43BBE7" />

        <TextView
            style="@style/text_flag_01"
            android:background="@drawable/flag_03"
            android:text="The love ing"
            android:textColor="#43BBE7" />

        <TextView
            style="@style/text_flag_01"
            android:background="@drawable/flag_03"
            android:text="Money ing"
            android:textColor="#43BBE7" />

        <TextView
            style="@style/text_flag_01"
            android:background="@drawable/flag_03"
            android:text="Hard" ing"
            android:textColor="#43BBE7" />

        <TextView
            style="@style/text_flag_01"
            android:background="@drawable/flag_03"
            android:text="I thick i can"
            android:textColor="#43BBE7" />
    </com.example.viewgroupdemo.MyViewGroup>

</LinearLayout>
Copy the code


\

Setting: android: layout_width = “200 dp”

<com.example.viewgroupdemo.MyViewGroup xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="200dp"
    android:layout_height="wrap_content"
    android:background="#FFFFFF" >

    <TextView
        style="@style/text_flag_01"
        android:background="@drawable/flag_04"
        android:text="Welcome"
        android:textColor="# 323232" />

    <TextView
        style="@style/text_flag_01"
        android:background="@drawable/flag_04"
        android:text="IT engineer"
        android:textColor="# 323232" />

    <TextView
        style="@style/text_flag_01"
        android:background="@drawable/flag_04"
        android:text="Learn ing"
        android:textColor="# 323232" />

    <TextView
        style="@style/text_flag_01"
        android:background="@drawable/flag_04"
        android:text="The love ing"
        android:textColor="# 323232" />

    <TextView
        style="@style/text_flag_01"
        android:background="@drawable/flag_04"
        android:text="Money ing"
        android:textColor="# 323232" />

    <TextView
        style="@style/text_flag_01"
        android:background="@drawable/flag_04"
        android:text="Hard" ing"
        android:textColor="# 323232" />

    <TextView
        style="@style/text_flag_01"
        android:background="@drawable/flag_04"
        android:text="I thick i can"
        android:textColor="# 323232" />

</com.example.viewgroupdemo.MyViewGroup>
Copy the code


\

\

package com.example.viewgroupdemo;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.LinearLayout;

public class MyViewGroup extends ViewGroup {
	public MyViewGroup(Context context) {

		this(context, null);
	}
	public MyViewGroup(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public MyViewGroup(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		Log.i("tag"."MyViewGroup");
	}
	/*** * Step 1: Override generateLayoutParams to determine ViewGroup LayoutParams * return an instance of MarginLayoutParams, So that's specifying our ViewGroup's LayoutParams as MarginLayoutParams */
	@Override
	public LayoutParams generateLayoutParams(AttributeSet attrs) {
		Log.i("tag"."generateLayoutParams");
		return  new MarginLayoutParams(getContext(), attrs);
	}
	/** * * Calculate the width and height of all childViews, * then set the viewGroup height and width according to the width, height and margin of childView (MarginLayoutParams get margin) */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		Log.i("tag"."onMeasure");
		// Get the mode and height and width of the parent container
		int widthSpec = MeasureSpec.getSize(widthMeasureSpec);
		int widthMode = MeasureSpec.getMode(widthMeasureSpec);
		int heightSpec = MeasureSpec.getSize(heightMeasureSpec);
		int heightMode = MeasureSpec.getMode(heightMeasureSpec);
		// Record the height and width in the case of warp_content
		int width = 0;
		int height = 0;
		// Record the height and width of the current row
		int lineWidth =0;
		int lineheight = 0;
		//Layoutparams 
		MarginLayoutParams mlp = null;
		// Get the number of childViews
		int childCount = getChildCount();
		for (int i = 0; i < childCount; i++) {
			View childview = getChildAt(i);
			// Measure the height and width of childView
			measureChild(childview, widthMeasureSpec, heightMeasureSpec);

			/ / get LayoutParams
			mlp = (MarginLayoutParams) childview.getLayoutParams();

			// Get the height and width of the actual space occupied by childView
			int childWidth = childview.getMeasuredWidth()+mlp.leftMargin+mlp.rightMargin;
			int childHeight = childview.getMeasuredHeight()+mlp.topMargin+mlp.bottomMargin;

			// If lineWidth + chilWidth > viewGroup Max width, childView is moved to the next line
			if(lineWidth + childWidth >  widthSpec){/ / a newline
				height += lineheight;
				width = Math.max(lineWidth, childWidth);
				lineWidth = childWidth;// The next line is entered
			}else {// For the same line, the width increases
				lineWidth = lineWidth + childWidth;
				// Determine the maximum height of a row
				lineheight = Math.max(childHeight, lineheight);
			}

			// If it is the last, the maximum width of the current record is compared with the current lineWidth
			if (i == childCount - 1) { width = Math.max(width, lineWidth); height += lineheight; }}// Set the height and width of the ViewGroup according to the mode
		setMeasuredDimension(
				widthMode==MeasureSpec.EXACTLY ? widthSpec : width, 
						heightMode==MeasureSpec.EXACTLY ? heightSpec : height);
	}

	/** * Set the position of childView */
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		Log.i("tag"."onLayout");
		// Record the height and width in the case of warp_content
		int height = 0;
		// Record the height and width of the current row
		int lineWidth =0;
		int lineheight = 0;
		//Layoutparams 
		MarginLayoutParams mlp = null;
		// Get the number of childViews
		int childCount = getChildCount();
		for (int i = 0; i < childCount; i++) {
			View childview = getChildAt(i); 
			/ / childview area
			int cl = 0, ct = 0, cr = 0, cb = 0;
			mlp = (MarginLayoutParams) childview.getLayoutParams();
			// Get the height and width of the actual space occupied by childView
			int childWidth = childview.getMeasuredWidth()+mlp.leftMargin+mlp.rightMargin;
			int childHeight = childview.getMeasuredHeight()+mlp.topMargin+mlp.bottomMargin;

			// If lineWidth + chilWidth > viewGroup Max width, childView is moved to the next line
			if(lineWidth + childWidth >  getWidth()){/ / a newline
				height += lineheight;
				lineWidth = childWidth;// The next line is entered
				cl = mlp.leftMargin;
				ct = height + mlp.rightMargin;

			}else {// For the same line, the width increases
				cl = lineWidth+mlp.leftMargin;
				ct = height + mlp.topMargin;

				lineWidth = lineWidth + childWidth;
				// Determine the maximum height of a rowlineheight = Math.max(childHeight, lineheight); } cr = cl + childview.getMeasuredWidth(); cb = ct + childview.getMeasuredHeight(); childview.layout(cl, ct, cr, cb); }}}Copy the code


\

\

\