Android Custom ViewGroup real-story implementation FlowLayout

Source: Internet
Author: User

Reprint please indicate source: http://blog.csdn.net/lmj623565791/article/details/38352503, this article from "Zhang Hongyang's Blog"

1. Overview

The previous article has basically introduced how to customize the ViewGroup, if you do not understand, please check: Android handteach you to customize the ViewGroup , this article will use the method described in the previous article, to bring an example: to achieve FlowLayout, What is FlowLayout, if you are familiar with the Java swing is not unfamiliar, is the control according to the width of viewgroup, automatically add to the right, if the current line is not enough space, then automatically added to the next row. A little bit of all the controls are going to the left, the first line is full, the second line is floating ~ so also called flow layout. Android does not provide streaming layouts, but in some cases, streaming layouts are well suited for use, such as keyword tags, search hot word lists, and so on, such as:


These are especially suitable for use with FlowLayout, this blog will lead you to implement FlowLayout, and then use our own defined FlowLayout to achieve the above label effect. By the way, GitHub already has this flowlayout, but I feel that it does not affect our study of it, learn to use a control and learn to write a control, I believe we all understand that the granting of fish is better than giving people to fishing.

2. Simple analysis

1, for FlowLayout, need to specify the Layoutparams, we currently only need to be able to identify the margin, that is, the use of marginlayoutparams.

2, onmeasure calculate the width and height of all childview, and then according to the width and height of childview, calculate their width and height. (Of course, if it's not wrap_content, just use the calculated value passed in by the parent ViewGroup)

3, OnLayout all the Childview in the layout.

3, Generatelayoutparams

Because we only need to support margin, so we use the marginlayoutparams of the system directly

@Overridepublic viewgroup.layoutparams generatelayoutparams (AttributeSet attrs) {return new Marginlayoutparams ( GetContext (), attrs);}

4, Onmeasure

/** * is responsible for setting the measurement mode and size of the child control set its own width and height according to all child controls */@Overrideprotected void onmeasure (int widthmeasurespec, int heightmeasurespec) { Super.onmeasure (Widthmeasurespec, heightmeasurespec);//gets its parent container set for it the measurement mode and size int sizewidth = Measurespec.getsize ( WIDTHMEASURESPEC); int sizeheight = Measurespec.getsize (heightmeasurespec); int modewidth = Measurespec.getmode ( WIDTHMEASURESPEC); int modeheight = Measurespec.getmode (Heightmeasurespec); LOG.E (TAG, Sizewidth + "," + sizeheight);//If it is warp_content case, record width and height int width = 0;int height = 0;/** * Record the width of each row, and width continuously takes maximum Width */int linewidth = 0;/** * height of each row, accumulated to height */int lineheight = 0;int ccount = Getchildcount ();//traverse each child element for (int i = 0; i < ccount; i++) {View child = Getchildat (i);//measure each child's width and height measurechild (child, Widthmeasurespec, heightmeasurespec);// Get the child's lpmarginlayoutparams LP = (marginlayoutparams) child.getlayoutparams ();//The width of the current subspace actually occupies int childwidth = Child.getmeasuredwidth () + lp.leftmargin+ lp.rightmargin;//The height that the current subspace actually occupies int childheight = child.getmeasuredHeight () + lp.topmargin+ lp.bottommargin;/** * If the current child is added, the maximum width is exceeded, then the maximum width to the current, class plus height then open a new line */if (LineWidth + Childwidth > Sizewidth) {width = Math.max (linewidth, childwidth);//Take the largest linewidth = Childwidth;//re-open new line, start record//overlay current height , height + = lineheight;//to open record the next line of altitude lineheight = childheight;} else//otherwise accumulative value linewidth,lineheight take maximum height {linewidth + = Childwidth;lineheight = Math.max (lineheight, childheight);} If it is the last, compare the maximum width of the current record with the current linewidth if (i = = cCount-1) {width = Math.max (width, linewidth); height + = lineheight;}} Setmeasureddimension (Modewidth = = measurespec.exactly)? sizewidth:width, (modeheight = = measurespec.exactly)? Sizeheight:height);}

First, we get the measured mode and the high value of the parent container, then traverse all the childview and measure all the Childview using the Measurechild method. Then the width and height of the viewgroup are obtained according to the measurements of all childview and the width and height if set to Wrap_content. Finally, according to the pattern, if the measurespec.exactly is directly using the parent ViewGroup incoming width and height, otherwise set to calculate the width and height.

5, OnLayout

Specify the position and size of all childview in OnLayout

/** * Store all View, record by row */private list<list<view>> mallviews = new arraylist<list<view>> ();/** * Record the maximum height of each row */private list<integer> mlineheight = new arraylist<integer> (); @Overrideprotected 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;// Store all childviewlist<view> lineviews = new arraylist<view> () in each row, int ccount = Getchildcount ();//Traverse all children 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 line break is required (Childwidth + lp.leftmargin + lp.rightmargin + linewidth > width) {//Record all view and maximum height Mlineheight.add (lineheight) of this line;//save Childview of the current row, The new ArrayList is then opened to save the next line of Childviewmallviews.add (lineviews), linewidth = 0;//Resets the line width lineviews = new arraylist<view> ();} /** * If no line break is required, the cumulative */linewidth + = childwidth + lp.leftmargin + lp.rightmargin;lineheight = Math.max (lineheight, ChildHeight + lp.topMargin+ Lp.bottommargin); Lineviews.add (child);} Record the last line Mlineheight.add (lineheight); Mallviews.add (lineviews); int left = 0;int top = 0;//get total rows int linenums = MALLVIEWS.S Ize (); for (int i = 0; i < linenums; i++) {//all viewslineviews of each row = Mallviews.get (i);//maximum height of the current row lineheight = Mlineheigh T.get (i); LOG.E (TAG, "first" + i + "line:" + lineviews.size () + "," + lineviews); LOG.E (TAG, "first" + i + "line,:" + lineheight);//Traverse all viewfor of the current row (int j = 0; J < Lineviews.size (), j + +) {View child = Linevi Ews.get (j); if (child.getvisibility () = = View.gone) {continue;} Marginlayoutparams LP = (marginlayoutparams) child.getlayoutparams ();//calculate Childview left,top,right,bottomint LC = Left + Lp.leftmargin;int TC = top + lp.topmargin;int RC =LC + child.getmeasuredwidth (); int BC = TC + child.getmeasuredheight (); LOG.E (TAG, 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;}}

Each item of the AllViews is a list collection of all view's in each row.

The maximum height of each row is recorded by the mlineheight.

23-48 rows, traversing all Childview, to set the value of AllViews, and the value of Mlineheight.

57 rows, traversing all rows according to the length of the AllViews

67-91 rows, traversing all the childview in each row, the Childview left, top, right, bottom are computed, and positioned.

92-93 rows, resets left and top, ready to calculate the position of the next line of Childview.

Well, to this finish all the Childview of the drawing area of the determination, to this, our FlowLayout code also ended ~ ~ Calm down to see if it is not difficult ~

6. Testing

I'm going to use TextView as our label, so it's simple to write a little style:

In Res/values/styles.xml:

<style name= "text_flag_01" >        <item name= "Android:layout_width" >wrap_content</item>        < Item Name= "Android:layout_height" >wrap_content</item>        <item name= "Android:layout_margin" >4DP </item>        <item name= "Android:background" > @drawable/flag_01</item>        <item name= " Android:textcolor "> #ffffff </item>    </style>

Flag_01.xml

<?xml version= "1.0" encoding= "Utf-8"? ><shape xmlns:android= "Http://schemas.android.com/apk/res/android" >    <solid android:color= "#7690A5" >    </solid>    <corners android:radius= "5DP"/>    <padding        android:bottom= "2DP"        android:left= "10DP"        android:right= "10DP"        android:top= "2DP"/ ></shape>

Layout file:

<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:backgro Und= "#E1E6F6" android:orientation= "vertical" > <com.zhy.zhy_flowlayout02.            FlowLayout android:layout_width= "fill_parent" android:layout_height= "wrap_content" > <TextView style= "@style/text_flag_01" android:text= "Welcome"/> <textview style= "@styl            E/text_flag_01 "android:text=" it engineer "/> <textview style=" @style/text_flag_01 " android:text= "learning ing"/> <textview style= "@style/text_flag_01" android:text= "Love ing"/&        Gt <textview style= "@style/text_flag_01" android:text= "earn money ing"/> <textview s tyle= "@style/text_flag_01" android:text= "hard ing"/> &Lt TextView style= "@style/text_flag_01" android:text= "I thick I Can"/> </com.zhy.zhy_flowlayo ut02. Flowlayout> </LinearLayout>


is not that good, the following continues to be simple to customize several backgrounds:

Res/drawble/flog_02.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= "40DP"/>    <stroke android:color= "#C9C9C9" android:width= "2DP"/>        <padding        android:bottom= "2DP"        android:left= "10DP"        android:right= "10DP"        android:top= "2DP"/></shape>

Flag_03.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= "40DP"/>        <padding        android:bottom= "2DP"        android:left= "10DP"        android:right= "10DP"        android:top= " 2DP "/></shape>

Layout file:

<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:backgro Und= "#E1E6F6" android:orientation= "vertical" > <com.zhy.zhy_flowlayout02.            FlowLayout android:layout_width= "fill_parent" android:layout_height= "wrap_content" > <TextView style= "@style/text_flag_01" android:text= "Welcome"/> <textview style= "@styl            E/text_flag_01 "android:text=" it engineer "/> <textview style=" @style/text_flag_01 " android:text= "learning ing"/> <textview style= "@style/text_flag_01" android:text= "Love ing"/&        Gt <textview style= "@style/text_flag_01" android:text= "earn money ing"/> <textview s tyle= "@style/text_flag_01" android:text= "hard ing"/> &Lt TextView style= "@style/text_flag_01" android:text= "I thick I Can"/> </com.zhy.zhy_flowlayo ut02. Flowlayout> <com.zhy.zhy_flowlayout02. FlowLayout android:layout_width= "fill_parent" android:layout_height= "Wrap_content" Android:layout_mar gintop= "20DP" > <textview style= "@style/text_flag_01" android:background= "@drawable/fla G_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= "@draw            Able/flag_02 "android:text=" learning ing "android:textcolor=" #888888 "/> <textview          style= "@style/text_flag_01" android:background= "@drawable/flag_02"  android:text= "Love ing" android:textcolor= "#888888"/> <textview style= "@style/text_flag _01 "android:background=" @drawable/flag_02 "android:text=" earn money ing "android:textcolor=" #8888            "/> <textview style=" @style/text_flag_01 "android:background=" @drawable/flag_02 " android:text= "Hard ing" android:textcolor= "#888888"/> <textview style= "@style/tex T_flag_01 "android:background=" @drawable/flag_02 "android:text=" I thick I Can "android:te Xtcolor= "#888888"/> </com.zhy.zhy_flowlayout02. Flowlayout> <com.zhy.zhy_flowlayout02. FlowLayout android:layout_width= "fill_parent" android:layout_height= "Wrap_content" Android:layout_mar gintop= "20DP" > <textview style= "@style/text_flag_01" android:background= "@drawable/fla   G_03 "android:text=" Welcome "         Android:textcolor= "#43BBE7"/> <textview style= "@style/text_flag_01" android:b ackground= "@drawable/flag_03" android:text= "it Engineer" android:textcolor= "#43BBE7"/> <text View style= "@style/text_flag_01" android:background= "@drawable/flag_03" android:text= "Learning I Ng "android:textcolor=" #43BBE7 "/> <textview style=" @style/text_flag_01 "and roid:background= "@drawable/flag_03" android:text= "Love ing" android:textcolor= "#43BBE7"/> &L T TextView style= "@style/text_flag_01" android:background= "@drawable/flag_03" android:text=            "Earning ing" android:textcolor= "#43BBE7"/> <textview style= "@style/text_flag_01"        android:background= "@drawable/flag_03" android:text= "efforts to 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.zhy.zhy_flowlayout02. Flowlayout></linearlayout>


I don't like it. The above are fixed under the width of the match_parent~~, to achieve the first mobile development of the article Popular Tags:

Flag_04.xml

<?xml version= "1.0" encoding= "Utf-8"? ><shape xmlns:android= "Http://schemas.android.com/apk/res/android" >    <solid android:color= "#E7E7E7" >    </solid>    <corners        android:radius= "30DP"         />    <padding        android:bottom= "2DP"        android:left= "10DP"        android:right= "10DP"        android:top= "2DP"/></shape>

Layout file:

<com.zhy.zhy_flowlayout02. FlowLayout 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 "> &lt ;        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= "@draw Able/flag_04 "android:text=" it Engineer "android:textcolor=" #323232 "/> <textview style=" @style/te Xt_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= "Love ing" android:textcolor= "#323232"/> <textview style= "@style/text_flag_01" Android:backgro und= "@drawable/flag_04" android:text= "Make money ing" android:textcolor= "#323232"/> <textview style= "@s Tyle/text_flag_01 "android:background=" @drawable/flag_04 "android:text=" efforts to ing "android:textcolor=" #32 3232 "/> <textview style=" @style/text_flag_01 "android:background=" @drawable/flag_04 "Androi d:text= "I thick I Can" android:textcolor= "#323232"/></com.zhy.zhy_flowlayout02. Flowlayout>


is not exactly the same ~~o ~


If you think this blog is useful for you, then leave a message or the top one ~ ~


SOURCE Click to download







Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.