preface

The actual project needs to implement a popular search column, similar to the following: Since the text in the sub-view is variable, the number of sub-items that can be displayed in a line is also uncertain. Need to support wrapping and calculating positions.

\

\

�# Use the open source library SimpleFlowLayout

I wrote my own custom view, inherited from viewGroup, to implement it, hosted on github open source platform.

Name: SimpleFlowLayout address: https://github.com/vir56k/SimpleFlowLayout features: can keep adding more child view, the calculation of position, the word wrap. Similar to HTML div tags apply to: hot tagsCopy the code

Implementation approach

To implement a custom viewGroup, you need:

  1. Inherited from the ViewGroup
  2. Protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) this method is used to measure the width and height of your own (custom view)
  3. Protected void onLayout(Boolean changed, int L, int T, int r, int B) This method specifies how to place child views.

The implementation code

package zhangyf.vir56k.flowframelayout; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; /** * name: Android simple stream layout custom view ** ** features: can constantly add multiple sub-view, calculate position, automatic line wrap. * applies: Created by Zhangyunfei on 15/12/4. */ public class SimpleFlowLayout extends ViewGroup {public SimpleFlowLayout(Context context) { super(context); } public SimpleFlowLayout(Context context, AttributeSet attrs) { super(context, attrs); } public SimpleFlowLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMax = MeasureSpec.getSize(widthMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMax = MeasureSpec.getSize(heightMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthNeed = 0; int heightNeed = 0; int x = 0; int y = 0; int currentLineHeight = 0; View child; for (int i = 0; i < getChildCount(); i++) { child = getChildAt(i); if (child.getVisibility() == View.GONE) { continue; } child.measure(widthMeasureSpec, heightMeasureSpec); MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); // Measure the width of the child view. Int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; // Use measureChildWithMargins on viewGroup to measure the width, Int childHeight = child.getMeasuredHeight() + lp.topmargin + lp.bottomMargin; measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; If (x + childWidth > widthMax) {// if (x + childWidth > widthMax) { currentLineHeight = 0; x = 0; } x += childWidth; currentLineHeight = Math.max(currentLineHeight, childHeight); widthNeed = Math.max(widthNeed, x); HeightNeed = math. Max (heightNeed, y + currentLineHeight); SetMeasuredDimension (widthMode == MeasureSpec.EXACTLY? widthMax : widthNeed, heightMode == MeasureSpec.EXACTLY ? heightMax : heightNeed); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int widthMax = getWidth(); int x, y; x = 0; y = 0; View child; int left = 0; int top = 0; int currentLineHeight = 0; for (int i = 0; i < getChildCount(); i++) { child = getChildAt(i); if (child.getVisibility() == View.GONE) { continue; } MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; If (x + childWidth > widthMax) {if (x + childWidth > widthMax) { x = 0; currentLineHeight = 0; } left = x + lp.leftMargin; top = y + lp.topMargin; Child.layout (left, top, left + child.getMeasuredWidth(), Top + Child.getMeasuredHeight ()); x += childWidth; currentLineHeight = Math.max(currentLineHeight, childHeight); } } @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(),  attrs); }}Copy the code