Android中常见的热门标签的流式布局的实现

来源:互联网 发布:电力电子仿真软件 编辑:程序博客网 时间:2024/05/21 08:16
Bitbucket 让 pull request变得更强大,可即刻提升团队代码质量     云计算行业圆桌论坛     前端精品课程免费看,写课评赢心动大礼!
 

Android中常见的热门标签的流式布局的实现

 9999人阅读 评论(15) 收藏 举报
 分类:
 
 

目录(?)[+]

一、概述:
在日常的app使用中,我们会在android 的app中看见 热门标签等自动换行的流式布局,今天,我们就来看看如何

自定义一个类似热门标签那样的流式布局吧源码下载在下面最后给出

类似的自定义布局。下面我们就来详细介绍流式布局的应用特点以及用的的技术点:

1.流式布局的特点以及应用场景
    特点:当上面一行的空间不够容纳新的TextView时候,
    才开辟下一行的空间

  原理图:

  

    场景:主要用于关键词搜索或者热门标签等场景
2.自定义ViewGroup,重点重写下面两个方法

    1、onMeasure:测量子view的宽高,设置自己的宽和高

    2、onLayout:设置子view的位置

    onMeasure:根据子view的布局文件中属性,来为子view设置测量模式和测量值
    测量=测量模式+测量值;

    测量模式有3种:
    EXACTLY:表示设置了精确的值,一般当childView设置其宽、高为精确值、match_parent时,ViewGroup会将其设置为EXACTLY;
    AT_MOST:表示子布局被限制在一个最大值内,一般当childView设置其宽、高为wrap_content时,ViewGroup会将其设置为AT_MOST;
    UNSPECIFIED:表示子布局想要多大就多大,一般出现在AadapterView的item的heightMode中、ScrollView的childView的heightMode中;此种模式比较少见。
3.LayoutParams
    ViewGroup LayoutParams :每个 ViewGroup 对应一个 LayoutParams; 即 ViewGroup -> LayoutParams
    getLayoutParams 不知道转为哪个对应的LayoutParams ,其实很简单,就是如下:
    子View.getLayoutParams 得到的LayoutParams对应的就是 子View所在的父控件的LayoutParams;
    例如,LinearLayout 里面的子view.getLayoutParams ->LinearLayout.LayoutParams
    所以 咱们的FlowLayout 也需要一个LayoutParams,由于上面的效果图是子View的 margin,
    所以应该使用MarginLayoutParams。即FlowLayout->MarginLayoutParams

4.最后来看看实现的最终效果图:


二、热门标签的流式布局的实现:

1. 自定义热门标签的ViewGroup实现

  根据上面的技术分析,自定义类继承于ViewGroup,并重写 onMeasure和onLayout等方法。具体实现代码如下:

[plain] view plaincopy
  1. package com.czm.flowlayout;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import android.content.Context;  
  7. import android.util.AttributeSet;  
  8. import android.view.View;  
  9. import android.view.ViewGroup;  
  10. /**  
  11.  *   
  12.  * @author caizhiming  
  13.  * @created on 2015-4-13  
  14.  */  
  15. public class XCFlowLayout extends ViewGroup{  
  16.   
  17.     //存储所有子View  
  18.     private List<List<View>> mAllChildViews = new ArrayList<>();  
  19.     //每一行的高度  
  20.     private List<Integer> mLineHeight = new ArrayList<>();  
  21.       
  22.     public XCFlowLayout(Context context) {  
  23.         this(context, null);  
  24.         // TODO Auto-generated constructor stub  
  25.     }  
  26.     public XCFlowLayout(Context context, AttributeSet attrs) {  
  27.         this(context, attrs, 0);  
  28.         // TODO Auto-generated constructor stub  
  29.     }  
  30.     public XCFlowLayout(Context context, AttributeSet attrs, int defStyle) {  
  31.         super(context, attrs, defStyle);  
  32.         // TODO Auto-generated constructor stub  
  33.     }  
  34.     @Override  
  35.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  36.         // TODO Auto-generated method stub  
  37.           
  38.         //父控件传进来的宽度和高度以及对应的测量模式  
  39.         int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);  
  40.         int modeWidth = MeasureSpec.getMode(widthMeasureSpec);  
  41.         int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);  
  42.         int modeHeight = MeasureSpec.getMode(heightMeasureSpec);  
  43.           
  44.         //如果当前ViewGroup的宽高为wrap_content的情况  
  45.         int width = 0;//自己测量的 宽度  
  46.         int height = 0;//自己测量的高度  
  47.         //记录每一行的宽度和高度  
  48.         int lineWidth = 0;  
  49.         int lineHeight = 0;  
  50.           
  51.         //获取子view的个数  
  52.         int childCount = getChildCount();  
  53.         for(int i = 0;i < childCount; i ++){  
  54.             View child = getChildAt(i);  
  55.             //测量子View的宽和高  
  56.             measureChild(child, widthMeasureSpec, heightMeasureSpec);  
  57.             //得到LayoutParams  
  58.             MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();  
  59.             //子View占据的宽度  
  60.             int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;  
  61.             //子View占据的高度  
  62.             int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;  
  63.             //换行时候  
  64.             if(lineWidth + childWidth > sizeWidth){  
  65.                 //对比得到最大的宽度  
  66.                 width = Math.max(width, lineWidth);  
  67.                 //重置lineWidth  
  68.                 lineWidth = childWidth;  
  69.                 //记录行高  
  70.                 height += lineHeight;  
  71.                 lineHeight = childHeight;  
  72.             }else{//不换行情况  
  73.                 //叠加行宽  
  74.                 lineWidth += childWidth;  
  75.                 //得到最大行高  
  76.                 lineHeight = Math.max(lineHeight, childHeight);  
  77.             }  
  78.             //处理最后一个子View的情况  
  79.             if(i == childCount -1){  
  80.                 width = Math.max(width, lineWidth);  
  81.                 height += lineHeight;  
  82.             }  
  83.         }  
  84.         //wrap_content  
  85.         setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width,  
  86.                 modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height);  
  87.         super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  88.     }  
  89.       
  90.     @Override  
  91.     protected void onLayout(boolean changed, int l, int t, int r, int b) {  
  92.         // TODO Auto-generated method stub  
  93.         mAllChildViews.clear();  
  94.         mLineHeight.clear();  
  95.         //获取当前ViewGroup的宽度  
  96.         int width = getWidth();  
  97.           
  98.         int lineWidth = 0;  
  99.         int lineHeight = 0;  
  100.         //记录当前行的view  
  101.         List<View> lineViews = new ArrayList<View>();  
  102.         int childCount = getChildCount();  
  103.         for(int i = 0;i < childCount; i ++){  
  104.             View child = getChildAt(i);  
  105.             MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();  
  106.             int childWidth = child.getMeasuredWidth();  
  107.             int childHeight = child.getMeasuredHeight();  
  108.               
  109.             //如果需要换行  
  110.             if(childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width){  
  111.                 //记录LineHeight  
  112.                 mLineHeight.add(lineHeight);  
  113.                 //记录当前行的Views  
  114.                 mAllChildViews.add(lineViews);  
  115.                 //重置行的宽高  
  116.                 lineWidth = 0;  
  117.                 lineHeight = childHeight + lp.topMargin + lp.bottomMargin;  
  118.                 //重置view的集合  
  119.                 lineViews = new ArrayList();  
  120.             }  
  121.             lineWidth += childWidth + lp.leftMargin + lp.rightMargin;  
  122.             lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + lp.bottomMargin);  
  123.             lineViews.add(child);  
  124.         }  
  125.         //处理最后一行  
  126.         mLineHeight.add(lineHeight);  
  127.         mAllChildViews.add(lineViews);  
  128.           
  129.         //设置子View的位置  
  130.         int left = 0;  
  131.         int top = 0;  
  132.         //获取行数  
  133.         int lineCount = mAllChildViews.size();  
  134.         for(int i = 0; i < lineCount; i ++){  
  135.             //当前行的views和高度  
  136.             lineViews = mAllChildViews.get(i);  
  137.             lineHeight = mLineHeight.get(i);  
  138.             for(int j = 0; j < lineViews.size(); j ++){  
  139.                 View child = lineViews.get(j);  
  140.                 //判断是否显示  
  141.                 if(child.getVisibility() == View.GONE){  
  142.                     continue;  
  143.                 }  
  144.                 MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();  
  145.                 int cLeft = left + lp.leftMargin;  
  146.                 int cTop = top + lp.topMargin;  
  147.                 int cRight = cLeft + child.getMeasuredWidth();  
  148.                 int cBottom = cTop + child.getMeasuredHeight();  
  149.                 //进行子View进行布局  
  150.                 child.layout(cLeft, cTop, cRight, cBottom);  
  151.                 left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;  
  152.             }  
  153.             left = 0;  
  154.             top += lineHeight;  
  155.         }  
  156.           
  157.     }  
  158.     /**  
  159.      * 与当前ViewGroup对应的LayoutParams  
  160.      */  
  161.     @Override  
  162.     public LayoutParams generateLayoutParams(AttributeSet attrs) {  
  163.         // TODO Auto-generated method stub  
  164.           
  165.         return new MarginLayoutParams(getContext(), attrs);  
  166.     }  
  167. }  

2.相关的布局文件:

引用自定义控件:

[plain] view plaincopy
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:id="@+id/container"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent" >  
  6.   
  7.     <com.czm.flowlayout.XCFlowLayout  
  8.         android:id="@+id/flowlayout"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="match_parent" >  
  11.   
  12.     </com.czm.flowlayout.XCFlowLayout>  
  13.   
  14. </RelativeLayout>  

TextView的样式文件:

[plain] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android" >  
  3.     <solid android:color="#666666" />  
  4.     <corners android:radius="10dp" />  
  5.     <padding   
  6.         android:left="5dp"  
  7.         android:right="5dp"  
  8.         android:top="5dp"  
  9.         android:bottom="5dp"   
  10.         />  
  11.   
  12. </shape>  

三、使用该自定义布局控件类

最后,如何使用该自定义的热门标签控件类呢?很简单,请看下面实例代码:

[plain] view plaincopy
  1. package com.czm.flowlayout;  
  2.   
  3. import android.app.Activity;  
  4. import android.graphics.Color;  
  5. import android.os.Bundle;  
  6. import android.view.ViewGroup.LayoutParams;  
  7. import android.view.ViewGroup.MarginLayoutParams;  
  8. import android.widget.TextView;  
  9. /**  
  10.  *   
  11.  * @author caizhiming  
  12.  * @created on 2015-4-13  
  13.  */  
  14. public class MainActivity extends Activity {  
  15.   
  16.     private String mNames[] = {  
  17.             "welcome","android","TextView",  
  18.             "apple","jamy","kobe bryant",  
  19.             "jordan","layout","viewgroup",  
  20.             "margin","padding","text",  
  21.             "name","type","search","logcat"  
  22.     };  
  23.     private XCFlowLayout mFlowLayout;  
  24.     @Override  
  25.     protected void onCreate(Bundle savedInstanceState) {  
  26.         super.onCreate(savedInstanceState);  
  27.         setContentView(R.layout.activity_main);  
  28.           
  29.         initChildViews();  
  30.           
  31.     }  
  32.     private void initChildViews() {  
  33.         // TODO Auto-generated method stub  
  34.         mFlowLayout = (XCFlowLayout) findViewById(R.id.flowlayout);  
  35.         MarginLayoutParams lp = new MarginLayoutParams(  
  36.                 LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);  
  37.         lp.leftMargin = 5;  
  38.         lp.rightMargin = 5;  
  39.         lp.topMargin = 5;  
  40.         lp.bottomMargin = 5;  
  41.         for(int i = 0; i < mNames.length; i ++){  
  42.             TextView view = new TextView(this);  
  43.             view.setText(mNames[i]);  
  44.             view.setTextColor(Color.WHITE);  
  45.             view.setBackgroundDrawable(getResources().getDrawable(R.drawable.textview_bg));  
  46.             mFlowLayout.addView(view,lp);  
  47.         }  
  48.     }  
  49.   
  50. }  

四、源码下载

最后给出源码的下载:http://download.csdn.net/detail/jdsjlzx/8784571


这里引用另一个高手的实现,

摘要

新项目用到了一种全新布局————Android标签流式布局的功能,正好一直说给大家讲自定义控件的实现,今天就为大家讲一种android流式布局的实现。 
本文原创,转载请注明地址:http://blog.kymjs.com/

正文

在日常的app使用中,我们会在android 的app中看见热门标签等自动换行的流式布局,今天,我们就来看看如何自定义一个类似热门标签那样的流式布局吧(源码下载在下面最后给出)
OpenSourceLaboratory
这个控件并不是我实现的,代码是从网上搜流式布局找到的。我只是为大家讲解一下实现过程以及原理。

先看代码

<code class="language-java"><span class="kd"><span class="kwd">public</span></span><span class="pln"> </span><span class="kd"><span class="kwd">class</span></span><span class="pln"> </span><span class="nc"><span class="typ">FlowLayout</span></span><span class="pln"> </span><span class="kd"><span class="kwd">extends</span></span><span class="pln"> </span><span class="n"><span class="typ">ViewGroup</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">    </span><span class="kd"><span class="kwd">private</span></span><span class="pln"> </span><span class="kt"><span class="kwd">float</span></span><span class="pln"> </span><span class="n"><span class="pln">mVerticalSpacing</span></span><span class="o"><span class="pun">;</span></span><span class="pln"> </span><span class="c1"><span class="com">//每个item纵向间距</span></span><span class="pln">    </span><span class="kd"><span class="kwd">private</span></span><span class="pln"> </span><span class="kt"><span class="kwd">float</span></span><span class="pln"> </span><span class="n"><span class="pln">mHorizontalSpacing</span></span><span class="o"><span class="pun">;</span></span><span class="pln"> </span><span class="c1"><span class="com">//每个item横向间距</span></span><span class="pln">    </span><span class="kd"><span class="kwd">public</span></span><span class="pln"> </span><span class="nf"><span class="typ">FlowLayout</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="typ">Context</span></span><span class="pln"> </span><span class="n"><span class="pln">context</span></span><span class="o"><span class="pun">)</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">        </span><span class="kd"><span class="kwd">super</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">context</span></span><span class="o"><span class="pun">);</span></span><span class="pln">    </span><span class="o"><span class="pun">}</span></span><span class="pln">    </span><span class="kd"><span class="kwd">public</span></span><span class="pln"> </span><span class="nf"><span class="typ">FlowLayout</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="typ">Context</span></span><span class="pln"> </span><span class="n"><span class="pln">context</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="typ">AttributeSet</span></span><span class="pln"> </span><span class="n"><span class="pln">attrs</span></span><span class="o"><span class="pun">)</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">        </span><span class="kd"><span class="kwd">super</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">context</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">attrs</span></span><span class="o"><span class="pun">);</span></span><span class="pln">    </span><span class="o"><span class="pun">}</span></span><span class="pln">    </span><span class="kd"><span class="kwd">public</span></span><span class="pln"> </span><span class="kt"><span class="kwd">void</span></span><span class="pln"> </span><span class="nf"><span class="pln">setHorizontalSpacing</span></span><span class="o"><span class="pun">(</span></span><span class="kt"><span class="kwd">float</span></span><span class="pln"> </span><span class="n"><span class="pln">pixelSize</span></span><span class="o"><span class="pun">)</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">        </span><span class="n"><span class="pln">mHorizontalSpacing</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">pixelSize</span></span><span class="o"><span class="pun">;</span></span><span class="pln">    </span><span class="o"><span class="pun">}</span></span><span class="pln">    </span><span class="kd"><span class="kwd">public</span></span><span class="pln"> </span><span class="kt"><span class="kwd">void</span></span><span class="pln"> </span><span class="nf"><span class="pln">setVerticalSpacing</span></span><span class="o"><span class="pun">(</span></span><span class="kt"><span class="kwd">float</span></span><span class="pln"> </span><span class="n"><span class="pln">pixelSize</span></span><span class="o"><span class="pun">)</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">        </span><span class="n"><span class="pln">mVerticalSpacing</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">pixelSize</span></span><span class="o"><span class="pun">;</span></span><span class="pln">    </span><span class="o"><span class="pun">}</span></span><span class="pln">    </span><span class="nd"><span class="lit">@Override</span></span><span class="pln">    </span><span class="kd"><span class="kwd">protected</span></span><span class="pln"> </span><span class="kt"><span class="kwd">void</span></span><span class="pln"> </span><span class="nf"><span class="pln">onMeasure</span></span><span class="o"><span class="pun">(</span></span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">widthMeasureSpec</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">heightMeasureSpec</span></span><span class="o"><span class="pun">)</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">        </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">selfWidth</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">resolveSize</span></span><span class="o"><span class="pun">(</span></span><span class="mi"><span class="lit">0</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">widthMeasureSpec</span></span><span class="o"><span class="pun">);</span></span><span class="pln">        </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">getPaddingLeft</span></span><span class="o"><span class="pun">();</span></span><span class="pln">        </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingTop</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">getPaddingTop</span></span><span class="o"><span class="pun">();</span></span><span class="pln">        </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingRight</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">getPaddingRight</span></span><span class="o"><span class="pun">();</span></span><span class="pln">        </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingBottom</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">getPaddingBottom</span></span><span class="o"><span class="pun">();</span></span><span class="pln">        </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">childLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingLeft</span></span><span class="o"><span class="pun">;</span></span><span class="pln">        </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">childTop</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingTop</span></span><span class="o"><span class="pun">;</span></span><span class="pln">        </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">lineHeight</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="mi"><span class="lit">0</span></span><span class="o"><span class="pun">;</span></span><span class="pln">        </span><span class="c1"><span class="com">//通过计算每一个子控件的高度,得到自己的高度</span></span><span class="pln">        </span><span class="k"><span class="kwd">for</span></span><span class="pln"> </span><span class="o"><span class="pun">(</span></span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">i</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="mi"><span class="lit">0</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">childCount</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">getChildCount</span></span><span class="o"><span class="pun">();</span></span><span class="pln"> </span><span class="n"><span class="pln">i</span></span><span class="pln"> </span><span class="o"><span class="pun"><</span></span><span class="pln"> </span><span class="n"><span class="pln">childCount</span></span><span class="o"><span class="pun">;</span></span><span class="pln"> </span><span class="o"><span class="pun">++</span></span><span class="n"><span class="pln">i</span></span><span class="o"><span class="pun">)</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">            </span><span class="n"><span class="typ">View</span></span><span class="pln"> </span><span class="n"><span class="pln">childView</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">getChildAt</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">i</span></span><span class="o"><span class="pun">);</span></span><span class="pln">            </span><span class="n"><span class="typ">LayoutParams</span></span><span class="pln"> </span><span class="n"><span class="pln">childLayoutParams</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">childView</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">getLayoutParams</span></span><span class="o"><span class="pun">();</span></span><span class="pln">            </span><span class="n"><span class="pln">childView</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">measure</span></span><span class="o"><span class="pun">(</span></span><span class="pln">                    </span><span class="n"><span class="pln">getChildMeasureSpec</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">widthMeasureSpec</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingRight</span></span><span class="o"><span class="pun">,</span></span><span class="pln">                            </span><span class="n"><span class="pln">childLayoutParams</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">width</span></span><span class="o"><span class="pun">),</span></span><span class="pln">                    </span><span class="n"><span class="pln">getChildMeasureSpec</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">heightMeasureSpec</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingTop</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingBottom</span></span><span class="o"><span class="pun">,</span></span><span class="pln">                            </span><span class="n"><span class="pln">childLayoutParams</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">height</span></span><span class="o"><span class="pun">));</span></span><span class="pln">            </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">childWidth</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">childView</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">getMeasuredWidth</span></span><span class="o"><span class="pun">();</span></span><span class="pln">            </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">childHeight</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">childView</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">getMeasuredHeight</span></span><span class="o"><span class="pun">();</span></span><span class="pln">            </span><span class="n"><span class="pln">lineHeight</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="typ">Math</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">max</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">childHeight</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">lineHeight</span></span><span class="o"><span class="pun">);</span></span><span class="pln">            </span><span class="k"><span class="kwd">if</span></span><span class="pln"> </span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">childLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">childWidth</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingRight</span></span><span class="pln"> </span><span class="o"><span class="pun">></span></span><span class="pln"> </span><span class="n"><span class="pln">selfWidth</span></span><span class="o"><span class="pun">)</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">                </span><span class="n"><span class="pln">childLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingLeft</span></span><span class="o"><span class="pun">;</span></span><span class="pln">                </span><span class="n"><span class="pln">childTop</span></span><span class="pln"> </span><span class="o"><span class="pun">+=</span></span><span class="pln"> </span><span class="n"><span class="pln">mVerticalSpacing</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">lineHeight</span></span><span class="o"><span class="pun">;</span></span><span class="pln">                </span><span class="n"><span class="pln">lineHeight</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">childHeight</span></span><span class="o"><span class="pun">;</span></span><span class="pln">            </span><span class="o"><span class="pun">}</span></span><span class="pln"> </span><span class="k"><span class="kwd">else</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">                </span><span class="n"><span class="pln">childLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">+=</span></span><span class="pln"> </span><span class="n"><span class="pln">childWidth</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">mHorizontalSpacing</span></span><span class="o"><span class="pun">;</span></span><span class="pln">            </span><span class="o"><span class="pun">}</span></span><span class="pln">        </span><span class="o"><span class="pun">}</span></span><span class="pln">        </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">wantedHeight</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">childTop</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">lineHeight</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingBottom</span></span><span class="o"><span class="pun">;</span></span><span class="pln">        </span><span class="n"><span class="pln">setMeasuredDimension</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">selfWidth</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">resolveSize</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">wantedHeight</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">heightMeasureSpec</span></span><span class="o"><span class="pun">));</span></span><span class="pln">    </span><span class="o"><span class="pun">}</span></span><span class="pln">    </span><span class="nd"><span class="lit">@Override</span></span><span class="pln">    </span><span class="kd"><span class="kwd">protected</span></span><span class="pln"> </span><span class="kt"><span class="kwd">void</span></span><span class="pln"> </span><span class="nf"><span class="pln">onLayout</span></span><span class="o"><span class="pun">(</span></span><span class="kt"><span class="kwd">boolean</span></span><span class="pln"> </span><span class="n"><span class="pln">changed</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">l</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">t</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">r</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">b</span></span><span class="o"><span class="pun">)</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">        </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">myWidth</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">r</span></span><span class="pln"> </span><span class="o"><span class="pun">-</span></span><span class="pln"> </span><span class="n"><span class="pln">l</span></span><span class="o"><span class="pun">;</span></span><span class="pln">        </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">getPaddingLeft</span></span><span class="o"><span class="pun">();</span></span><span class="pln">        </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingTop</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">getPaddingTop</span></span><span class="o"><span class="pun">();</span></span><span class="pln">        </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingRight</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">getPaddingRight</span></span><span class="o"><span class="pun">();</span></span><span class="pln">        </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">childLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingLeft</span></span><span class="o"><span class="pun">;</span></span><span class="pln">        </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">childTop</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingTop</span></span><span class="o"><span class="pun">;</span></span><span class="pln">        </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">lineHeight</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="mi"><span class="lit">0</span></span><span class="o"><span class="pun">;</span></span><span class="pln">        </span><span class="c1"><span class="com">//根据子控件的宽高,计算子控件应该出现的位置。</span></span><span class="pln">        </span><span class="k"><span class="kwd">for</span></span><span class="pln"> </span><span class="o"><span class="pun">(</span></span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">i</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="mi"><span class="lit">0</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">childCount</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">getChildCount</span></span><span class="o"><span class="pun">();</span></span><span class="pln"> </span><span class="n"><span class="pln">i</span></span><span class="pln"> </span><span class="o"><span class="pun"><</span></span><span class="pln"> </span><span class="n"><span class="pln">childCount</span></span><span class="o"><span class="pun">;</span></span><span class="pln"> </span><span class="o"><span class="pun">++</span></span><span class="n"><span class="pln">i</span></span><span class="o"><span class="pun">)</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">            </span><span class="n"><span class="typ">View</span></span><span class="pln"> </span><span class="n"><span class="pln">childView</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">getChildAt</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">i</span></span><span class="o"><span class="pun">);</span></span><span class="pln">            </span><span class="k"><span class="kwd">if</span></span><span class="pln"> </span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">childView</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">getVisibility</span></span><span class="o"><span class="pun">()</span></span><span class="pln"> </span><span class="o"><span class="pun">==</span></span><span class="pln"> </span><span class="n"><span class="typ">View</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">GONE</span></span><span class="o"><span class="pun">)</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">                </span><span class="k"><span class="kwd">continue</span></span><span class="o"><span class="pun">;</span></span><span class="pln">            </span><span class="o"><span class="pun">}</span></span><span class="pln">            </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">childWidth</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">childView</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">getMeasuredWidth</span></span><span class="o"><span class="pun">();</span></span><span class="pln">            </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">childHeight</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">childView</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">getMeasuredHeight</span></span><span class="o"><span class="pun">();</span></span><span class="pln">            </span><span class="n"><span class="pln">lineHeight</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="typ">Math</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">max</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">childHeight</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">lineHeight</span></span><span class="o"><span class="pun">);</span></span><span class="pln">            </span><span class="k"><span class="kwd">if</span></span><span class="pln"> </span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">childLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">childWidth</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingRight</span></span><span class="pln"> </span><span class="o"><span class="pun">></span></span><span class="pln"> </span><span class="n"><span class="pln">myWidth</span></span><span class="o"><span class="pun">)</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">                </span><span class="n"><span class="pln">childLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingLeft</span></span><span class="o"><span class="pun">;</span></span><span class="pln">                </span><span class="n"><span class="pln">childTop</span></span><span class="pln"> </span><span class="o"><span class="pun">+=</span></span><span class="pln"> </span><span class="n"><span class="pln">mVerticalSpacing</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">lineHeight</span></span><span class="o"><span class="pun">;</span></span><span class="pln">                </span><span class="n"><span class="pln">lineHeight</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">childHeight</span></span><span class="o"><span class="pun">;</span></span><span class="pln">            </span><span class="o"><span class="pun">}</span></span><span class="pln">            </span><span class="n"><span class="pln">childView</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">layout</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">childLeft</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">childTop</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">childLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">childWidth</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">childTop</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">childHeight</span></span><span class="o"><span class="pun">);</span></span><span class="pln">            </span><span class="n"><span class="pln">childLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">+=</span></span><span class="pln"> </span><span class="n"><span class="pln">childWidth</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">mHorizontalSpacing</span></span><span class="o"><span class="pun">;</span></span><span class="pln">        </span><span class="o"><span class="pun">}</span></span><span class="pln">    </span><span class="o"><span class="pun">}</span></span><span class="pln"></span><span class="o"><span class="pun">}</span></span></code>

从控件创建过程说起

  1. 当这个流式布局在被加载如内存并显示在屏幕上这一过程中,首先会调用view.measure(w,h)这个方法,表示测量view的宽度与高度,其中参数w与h分别表示这个控件的父控件的宽高。
  2. 在view.measure()方法的调用过程中又会调用view本身的一个回调方法,onMeasure(),这个是view自身的一个回调方法,用于让开发者在自定义View的时候重新计算自身的大小。一般会在这个方法中循环遍历,计算出这个控件的全部子孙控件的宽高。
  3. 在View的宽高计算完成以后,考虑将这个控件显示到屏幕的指定位置上,此时view的onLayout()方法会被调用。 一般同时会在这个方法中计算出全部子孙控件在这个控件中的位置。
    可能基本流程有些枯燥,接下来结合代码看看。

流布局的实现

看到onMeasure()方法中的这段: //通过计算每一个子控件的高度,得到自己的高度

<code class="language-java"><span class="k"><span class="kwd">for</span></span><span class="pln"> </span><span class="o"><span class="pun">(</span></span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">i</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="mi"><span class="lit">0</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">childCount</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">getChildCount</span></span><span class="o"><span class="pun">();</span></span><span class="pln"> </span><span class="n"><span class="pln">i</span></span><span class="pln"> </span><span class="o"><span class="pun"><</span></span><span class="pln"> </span><span class="n"><span class="pln">childCount</span></span><span class="o"><span class="pun">;</span></span><span class="pln"> </span><span class="o"><span class="pun">++</span></span><span class="n"><span class="pln">i</span></span><span class="o"><span class="pun">)</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">    </span><span class="n"><span class="typ">View</span></span><span class="pln"> </span><span class="n"><span class="pln">childView</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">getChildAt</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">i</span></span><span class="o"><span class="pun">);</span></span><span class="pln">    </span><span class="n"><span class="typ">LayoutParams</span></span><span class="pln"> </span><span class="n"><span class="pln">childLayoutParams</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">childView</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">getLayoutParams</span></span><span class="o"><span class="pun">();</span></span><span class="pln">    </span><span class="n"><span class="pln">childView</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">measure</span></span><span class="o"><span class="pun">(</span></span><span class="pln">            </span><span class="n"><span class="pln">getChildMeasureSpec</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">widthMeasureSpec</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingRight</span></span><span class="o"><span class="pun">,</span></span><span class="pln">                    </span><span class="n"><span class="pln">childLayoutParams</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">width</span></span><span class="o"><span class="pun">),</span></span><span class="pln">            </span><span class="n"><span class="pln">getChildMeasureSpec</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">heightMeasureSpec</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingTop</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingBottom</span></span><span class="o"><span class="pun">,</span></span><span class="pln">                    </span><span class="n"><span class="pln">childLayoutParams</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">height</span></span><span class="o"><span class="pun">));</span></span><span class="pln">    </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">childWidth</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">childView</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">getMeasuredWidth</span></span><span class="o"><span class="pun">();</span></span><span class="pln">    </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">childHeight</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">childView</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">getMeasuredHeight</span></span><span class="o"><span class="pun">();</span></span><span class="pln">    </span><span class="n"><span class="pln">lineHeight</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="typ">Math</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">max</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">childHeight</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">lineHeight</span></span><span class="o"><span class="pun">);</span></span><span class="pln">    </span><span class="k"><span class="kwd">if</span></span><span class="pln"> </span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">childLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">childWidth</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingRight</span></span><span class="pln"> </span><span class="o"><span class="pun">></span></span><span class="pln"> </span><span class="n"><span class="pln">selfWidth</span></span><span class="o"><span class="pun">)</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">        </span><span class="n"><span class="pln">childLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingLeft</span></span><span class="o"><span class="pun">;</span></span><span class="pln">        </span><span class="n"><span class="pln">childTop</span></span><span class="pln"> </span><span class="o"><span class="pun">+=</span></span><span class="pln"> </span><span class="n"><span class="pln">mVerticalSpacing</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">lineHeight</span></span><span class="o"><span class="pun">;</span></span><span class="pln">        </span><span class="n"><span class="pln">lineHeight</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">childHeight</span></span><span class="o"><span class="pun">;</span></span><span class="pln">    </span><span class="o"><span class="pun">}</span></span><span class="pln"> </span><span class="k"><span class="kwd">else</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">        </span><span class="n"><span class="pln">childLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">+=</span></span><span class="pln"> </span><span class="n"><span class="pln">childWidth</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">mHorizontalSpacing</span></span><span class="o"><span class="pun">;</span></span><span class="pln">    </span><span class="o"><span class="pun">}</span></span><span class="pln"></span><span class="o"><span class="pun">}</span></span></code>

首先通过循环,遍历这个控件的所有子控件,同时调用子控件的measure()方法,这时measure方法的两个参数是控件能给这个子控件的最大宽高(我们都知道的,子控件再大,显示的大小也不能比父控件还大)。这里getChildMeasureSpec()方法的作用是用来计算一个合适子视图的尺寸大小(宽度或者高度),结合我们从子视图的LayoutParams所给出的MeasureSpec信息来获取最合适的结果。比如,如果这个View知道自己的大小尺寸(因为它本身的MeasureSpec的model为Exactly,)并且子视图的大小恰好跟父窗口一样大,父窗口必须用给定的大小去layout子视图 
参数含义:spec 父窗口传递给子视图的大小和模式
padding 父窗口的边距,也就是xml中的android:padding
childDimension 子视图想要绘制的准确大小,但最终不一定绘制此值

当得到了每一个子控件的大小以后,再要计算自己的宽高就简单了。
int wantedHeight = childTop + lineHeight + paddingBottom;

同理,在onLayout中的这一句

<code class="language-java"><span class="k"><span class="kwd">for</span></span><span class="pln"> </span><span class="o"><span class="pun">(</span></span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">i</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="mi"><span class="lit">0</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">childCount</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">getChildCount</span></span><span class="o"><span class="pun">();</span></span><span class="pln"> </span><span class="n"><span class="pln">i</span></span><span class="pln"> </span><span class="o"><span class="pun"><</span></span><span class="pln"> </span><span class="n"><span class="pln">childCount</span></span><span class="o"><span class="pun">;</span></span><span class="pln"> </span><span class="o"><span class="pun">++</span></span><span class="n"><span class="pln">i</span></span><span class="o"><span class="pun">)</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">    </span><span class="n"><span class="typ">View</span></span><span class="pln"> </span><span class="n"><span class="pln">childView</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">getChildAt</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">i</span></span><span class="o"><span class="pun">);</span></span><span class="pln">    </span><span class="k"><span class="kwd">if</span></span><span class="pln"> </span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">childView</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">getVisibility</span></span><span class="o"><span class="pun">()</span></span><span class="pln"> </span><span class="o"><span class="pun">==</span></span><span class="pln"> </span><span class="n"><span class="typ">View</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">GONE</span></span><span class="o"><span class="pun">)</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">        </span><span class="k"><span class="kwd">continue</span></span><span class="o"><span class="pun">;</span></span><span class="pln">    </span><span class="o"><span class="pun">}</span></span><span class="pln">    </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">childWidth</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">childView</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">getMeasuredWidth</span></span><span class="o"><span class="pun">();</span></span><span class="pln">    </span><span class="kt"><span class="kwd">int</span></span><span class="pln"> </span><span class="n"><span class="pln">childHeight</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">childView</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">getMeasuredHeight</span></span><span class="o"><span class="pun">();</span></span><span class="pln">    </span><span class="n"><span class="pln">lineHeight</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="typ">Math</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">max</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">childHeight</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">lineHeight</span></span><span class="o"><span class="pun">);</span></span><span class="pln">    </span><span class="k"><span class="kwd">if</span></span><span class="pln"> </span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">childLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">childWidth</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingRight</span></span><span class="pln"> </span><span class="o"><span class="pun">></span></span><span class="pln"> </span><span class="n"><span class="pln">myWidth</span></span><span class="o"><span class="pun">)</span></span><span class="pln"> </span><span class="o"><span class="pun">{</span></span><span class="pln">        </span><span class="n"><span class="pln">childLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">paddingLeft</span></span><span class="o"><span class="pun">;</span></span><span class="pln">        </span><span class="n"><span class="pln">childTop</span></span><span class="pln"> </span><span class="o"><span class="pun">+=</span></span><span class="pln"> </span><span class="n"><span class="pln">mVerticalSpacing</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">lineHeight</span></span><span class="o"><span class="pun">;</span></span><span class="pln">        </span><span class="n"><span class="pln">lineHeight</span></span><span class="pln"> </span><span class="o"><span class="pun">=</span></span><span class="pln"> </span><span class="n"><span class="pln">childHeight</span></span><span class="o"><span class="pun">;</span></span><span class="pln">    </span><span class="o"><span class="pun">}</span></span><span class="pln">    </span><span class="n"><span class="pln">childView</span></span><span class="o"><span class="pun">.</span></span><span class="na"><span class="pln">layout</span></span><span class="o"><span class="pun">(</span></span><span class="n"><span class="pln">childLeft</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">childTop</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">childLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">childWidth</span></span><span class="o"><span class="pun">,</span></span><span class="pln"> </span><span class="n"><span class="pln">childTop</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">childHeight</span></span><span class="o"><span class="pun">);</span></span><span class="pln">    </span><span class="n"><span class="pln">childLeft</span></span><span class="pln"> </span><span class="o"><span class="pun">+=</span></span><span class="pln"> </span><span class="n"><span class="pln">childWidth</span></span><span class="pln"> </span><span class="o"><span class="pun">+</span></span><span class="pln"> </span><span class="n"><span class="pln">mHorizontalSpacing</span></span><span class="o"><span class="pun">;</span></span><span class="pln"></span><span class="o"><span class="pun">}</span></span></code>

首先通过循环遍历,控制每个item子控件的显示位置,如果当前行还能放得下一个item,就放到当前行,如果放不下就放到下一行的最左边。
最终,遍历完成,也就相当于把自己的位置显示完成了。

效果截图

OpenSourceLaboratory



0
0

我的同类文章

 
  • Android 5.0+ 自定义普通按钮的ripple波纹效果2016-03-10
  • Android TextInputLayout修改提示信息文字颜色2016-03-08
  • Android Fragment传递参数Fragment.setArguments(Bundle bundle)2016-03-07
  • Android SwipeRefreshLayout 、RecyclerView冲突下拉冲突的解决方案2016-03-02
  • Android实现SwipeBack(右滑退出)效果2016-02-24
  • Android下拉刷新、滚动到底部自动加载更多RecyclerView组件2016-03-09
  • 最佳实践之Android代码规范2016-03-08
  • InstaMaterial:正确处理RecyclerView动画2016-03-06
  • android RecyclerView获得单个Item的ViewHolder2016-02-25
  • Android 立方体翻转效果2016-02-23
更多文章
猜你在找
精讲精练_参悟Android核心技术
Android底层技术:Java层系统服务(Android Service)
Android底层技术:Linux驱动框架与开发
Android应用的调试
Android平台技术:JNI开发初步
<iframe id="iframeu1607657_0" src="http://pos.baidu.com/acom?sz=728x90&amp;rdid=1607657&amp;dc=2&amp;di=u1607657&amp;dri=0&amp;dis=0&amp;dai=2&amp;ps=11141x235&amp;coa=at%3D3%26rsi0%3D728%26rsi1%3D90%26pat%3D6%26tn%3DbaiduCustNativeAD%26rss1%3D%2523FFFFFF%26conBW%3D1%26adp%3D1%26ptt%3D0%26titFF%3D%2525E5%2525BE%2525AE%2525E8%2525BD%2525AF%2525E9%25259B%252585%2525E9%2525BB%252591%26titFS%3D14%26rss2%3D%2523000000%26titSU%3D0%26ptbg%3D90%26piw%3D0%26pih%3D0%26ptp%3D0&amp;dcb=BAIDU_UNION_define&amp;dtm=BAIDU_DUP_SETJSONADSLOT&amp;dvi=0.0&amp;dci=-1&amp;dpt=none&amp;tsr=0&amp;tpr=1457683400685&amp;ti=Android%E4%B8%AD%E5%B8%B8%E8%A7%81%E7%9A%84%E7%83%AD%E9%97%A8%E6%A0%87%E7%AD%BE%E7%9A%84%E6%B5%81%E5%BC%8F%E5%B8%83%E5%B1%80%E7%9A%84%E5%AE%9E%E7%8E%B0%20-%20%E4%BA%AB%E5%8F%97%E6%8A%80%E6%9C%AF%E5%B8%A6%E6%9D%A5%E7%9A%84%E5%BF%AB%E4%B9%90%EF%BC%81%20-%20%E5%8D%9A%E5%AE%A2%E9%A2%91%E9%81%93%20-%20CSDN.NET&amp;ari=1&amp;dbv=2&amp;drs=1&amp;pcs=1196x589&amp;pss=1196x11157&amp;cfv=0&amp;cpl=4&amp;chi=1&amp;cce=true&amp;cec=UTF-8&amp;tlm=1457683401&amp;ltu=http%3A%2F%2Fblog.csdn.net%2Fjdsjlzx%2Farticle%2Fdetails%2F45042081%3Fref%3Dmyread&amp;ltr=https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3Dv66w3jz4iEDbFeyasaryjH22aQ5azn8VU5HBG2P3zIuvVVfYH_nTObNtiiFEIQiHYQEKhB4fSrVQKbt9407yzYFFD5ESx2_qJ-wWEVOQmmu%26wd%3D%26eqid%3D98b01bd7000aec590000000356e27bc3&amp;ecd=1&amp;psr=1280x800&amp;par=1280x705&amp;pis=-1x-1&amp;ccd=24&amp;cja=true&amp;cmi=6&amp;col=zh-CN&amp;cdo=-1&amp;tcn=1457683401&amp;qn=a7aa95acd283c4da&amp;tt=1457683400664.504.547.549" width="728" height="90" align="center,center" vspace="0" hspace="0" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true" style="border-width: 0px; border-style: initial; vertical-align: bottom; margin: 0px;"></iframe>
查看评论
11楼 Focus100 前天 14:08发表 [回复]
我简化了不少代码,效果一样,大家可以参考这篇:

http://blog.csdn.net/u013519989/article/details/50834180
10楼 huidawoxiaozi 2016-02-03 15:36发表 [回复]
放在scrollview冲突 :算出总高度,重新再设置一遍高度也可解决ViewGroup.LayoutParams params = flowlayout.getLayoutParams();
params.height = totalHeight;
flowlayout.setLayoutParams(params);
在界面加载完在这个方法里得到总高度public void onWindowFocusChanged(boolean hasFocus) {
9楼 路路路lbj 2016-01-05 10:39发表 [回复]
我的上下两行之间没有margin,可能是什么原因
8楼 o2jam0916 2015-11-17 19:56发表 [回复]
你好大神,我想问一下,我把这个标签流放大ListView中 就不显示了 是什么原因呢?求解 多谢
7楼 爱的不落叶 2015-10-26 13:55发表 [回复]
重写onMeasure方法最后不能调用父类的onMeasure方法。否则无法wrap_content。
6楼 yantaossg 2015-10-15 15:34发表 [回复]
非常感谢,提供的代码。
我想请问下,有没有办法。让每次新生成的标签背景颜色都不一样!
5楼 yunuoqzone19 2015-10-12 19:19发表 [回复]
解决自适应高度的方法是在onMeasure方法中 计算出高度调用setMeasuredDimension方法重新设置高度即可
4楼 AlexSucre 2015-09-08 11:11发表 [回复]
我想问一下,如果我想设置里面的文字居中显示怎么办?我现在想把这个每一个标签设置的比较大,然后居中显示
3楼 3kqing 2015-07-30 18:20发表 [回复]
这个布局放到ScrollView中不显示怎么办呢?XCFlowLayout如果高度设为wrap_content就不能显示。设为固定值才显示。有什么办法能让他设为wrap_content也显示呢?
Re: hzp901203 2015-08-18 13:54发表 [回复]
回复3kqing:把super.onMeasure(widthMeasureSpec, heightMeasureSpec);删掉就行了,并且将onMeasure里面的MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams(); 改成MarginLayoutParams lp =(MarginLayoutParams) child.getLayoutParams();,不然高度算的不对
Re: 596174 2015-11-06 15:17发表 [回复]
回复hzp901203:谢谢,这才是正解
2楼 又丑又不读书 2015-07-20 10:50发表 [回复]
这个布局放到ScrollView中不显示怎么办呢?XCFlowLayout如果高度设为wrap_content就不能显示。设为固定值才显示。有什么办法能让他设为wrap_content也显示呢?我是刚毕业的学生,项目中用到这个,弄了几天都解决不了。麻烦帮看下呢,谢谢了
Re: 一叶飘舟 2015-07-20 11:14发表 [回复]
回复又丑又不读书:下载这个代码:http://download.csdn.net/download/jdsjlzx/8784571
Re: yunuoqzone19 2015-10-12 20:11发表 [回复]
回复一叶飘舟:你这个还是没有解决自适应高度的问题 你哪个是设置的最大高度 - -。
1楼 又丑又不读书 2015-07-20 10:49发表 [回复]
这个布局放到ScrollView中不显示怎么办呢?XCFlowLayout如果高度设为wrap_content就不能显示。设为固定值才显示。有什么办法能让他设为wrap_content也显示呢?我是刚毕业的学生,项目中用到这个,弄了几天都解决不了。麻烦帮看下呢,谢谢了
发表评论
  • 用 户 名:
  • fygwfygyiq
  • 评论内容:
  • 插入代码
      
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
核心技术类目
全部主题 Hadoop AWS 移动游戏 Java Android iOS Swift 智能硬件 Docker OpenStack VPN Spark ERP IE10Eclipse CRM JavaScript 数据库 Ubuntu NFC WAP jQuery BI HTML5 Spring Apache .NET API HTMLSDK IIS Fedora XML LBS Unity Splashtop UML components Windows Mobile Rails QEMU KDE CassandraCloudStack FTC coremail OPhone CouchBase 云计算 iOS6 Rackspace Web App SpringSide Maemo Compuware大数据 aptech Perl Tornado Ruby Hibernate ThinkPHP HBase Pure Solr Angular Cloud Foundry Redis ScalaDjango Bootstrap
    个人资料
     
    一叶飘舟
     
    2
    • 访问:3818213次
    • 积分:43074
    • 等级: 
    • 排名:第49名
    • 原创:580篇
    • 转载:1430篇
    • 译文:7篇
    • 评论:1048条
    联系我
    QQ:573842281 

    希望能与更多的网友交流共同进步! 

    注意: 
    1.不要博客发私信; 
    2.请尽可能百度查询; 
    3.不回答环境调试、代码使用等类似问题(大家都要上班);
    4.提供有偿回答问题服务(如果问题对我有帮助,则免费)。

    文章分类
  • java(119)
  • java点滴(53)
  • jsp(7)
  • 技术前瞻(7)
  • 服务器(3)
  • Android开发(1500)
  • 音乐心情(13)
  • json(7)
  • 工作点滴(49)
  • C++(21)
  • Android UI(807)
  • 书籍推荐(2)
  • Android项目(7)
  • Socket(2)
  • Android开发 qq 表情(1)
  • Android通讯录(7)
  • Android系统(116)
  • Ubuntu(31)
  • 开源工具组件(58)
  • Android优化(65)
  • Android异常处理(6)
  • Android图片处理(63)
  • Android ListView(38)
  • Android新知识(21)
  • android fragment(27)
  • Android webview(11)
  • Android优化(1)
  • Android 视频(16)
  • java串口通信(9)
  • Android Animation(16)
  • Android NDK(1)
  • Android短彩信(6)
  • Android多媒体(28)
  • Android 网络(48)
  • Android 短彩信(2)
  • Android Sqlite(7)
  • Java 网络通信(6)
  • C(3)
  • 程序人生(8)
  • 加密算法(2)
  • 数据结构与算法(1)
  • 理财(1)
  • 支付宝(1)
    阅读排行
  • Fragment和FragmentActivity的使用方法 .(64875)
  • Android Material Design之Toolbar与Palette实践(64843)
  • Android屏幕适配全攻略(最权威的官方适配指导)(48427)
  • android状态栏一体化(改变状态栏的背景颜色)开源工程推荐(46077)
  • android EditText自定义样式(40890)
  • Android仿微信图片上传,可以选择多张图片,缩放预览,拍照上传等(40448)
  • HttpClient通过Post上传文件(25769)
  • Android网络框架Volley(25744)
  • Android搜索控件SearchView的用法(23726)
  • android 读取本地或网络图片,转换为Bitmap -(21202)
    评论排行
  • Android仿微信图片上传,可以选择多张图片,缩放预览,拍照上传等(86)
  • Android Material Design之Toolbar与Palette实践(48)
  • android状态栏一体化(改变状态栏的背景颜色)开源工程推荐(26)
  • android微信支付问题总结(20)
  • Android屏幕适配全攻略(最权威的官方适配指导)(17)
  • Android中常见的热门标签的流式布局的实现(15)
  • android状态栏一体化、沉浸式状态栏(兼容低版本)(14)
  • Android自定义捕获Application全局异常(12)
  • Android控件GridView之仿支付宝钱包首页带有分割线的GridView九宫格的完美实现(12)
  • Android 用代码查看本机保存的Wifi密码(11)
    推荐文章
    • *Networking Named Content 全文翻译
    • * 边缘检测与图像分割
    • * 数据库性能优化之SQL语句优化
    • *阿里巴巴发布《2015移动安全漏洞年报》
    • * Java经典设计模式之七大结构型模式(附实例和详解)
    • *网络性能评价方法
    最新评论
  • Android仿美团加载数据、小人奔跑进度动画对话框(附顺丰快递员奔跑效果)

    jihengsong: "我们使用到一个imageview.post(Runnable r)方法,因为帧动画需要不断的重画,...

  • Android在滚动列表中实现视频的播放(ListView & RecyclerView)

    醇酒醉影_ws: 赞一个!

  • Android之Design Support Library整理

    lzyang朝阳: 写的挺好的

  • Android中常见的热门标签的流式布局的实现

    Focus100: 我简化了不少代码,效果一样,大家可以参考这篇:http://blog.csdn.net/u01351...

  • Android自定义spinner下拉框实现的实现

    Ar_Braid: 看到Dota hero必须回一个,很赞!

  • Android App开源分享-在路上项目源码

    wuzhhh: 谢谢

  • Android Paint、Canvas、Matrix使用讲解(一、Paint)

    zsc_android: 写的很详细,不错。

  • Eclipse如何快速修改工程名及包名

    snsd_csdn: 感谢楼主,你的方法果然省事。

  • Android 通过Socket 和服务器通讯

    lyl7885000: 谢谢博主!

  • SlidingMenu最新版本使用详解

    qq_29132983: 你好有一个问题就是,在滑动打开添加动画的时候,背景颜色可以设置吗?比如缩放动画,缩放的时候背景颜色是...

0 0