在日常的app使用中,我们会在android 的app中看见热门标签等自动换行的流式布局,今天就为大家分享一种android流式布局的实现。

先看最终效果

自定义流式布局的实现

packagecom.sunny.flowlayout.view;importjava.util.ArrayList;importjava.util.List;importandroid.content.Context;importandroid.util.AttributeSet;importandroid.util.Log;importandroid.view.View;importandroid.view.ViewGroup;publicclassFlowLayoutextendsViewGroup{publicFlowLayout(Contextcontext,AttributeSetattrs,intdefStyle){super(context,attrs,defStyle);}publicFlowLayout(Contextcontext,AttributeSetattrs){this(context,attrs,0);}publicFlowLayout(Contextcontext){this(context,null);}@OverrideprotectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){intsizeWidth=MeasureSpec.getSize(widthMeasureSpec);intmodeWidth=MeasureSpec.getMode(widthMeasureSpec);intsizeHeight=MeasureSpec.getSize(heightMeasureSpec);intmodeHeight=MeasureSpec.getMode(heightMeasureSpec);//wrap_contentintwidth=0;intheight=0;//记录每一行的宽度与高度intlineWidth=0;intlineHeight=0;//得到内部元素的个数intcCount=getChildCount();for(inti=0;i<cCount;i++){Viewchild=getChildAt(i);//测量子View的宽和高measureChild(child,widthMeasureSpec,heightMeasureSpec);//得到LayoutParamsMarginLayoutParamslp=(MarginLayoutParams)child.getLayoutParams();//子View占据的宽度intchildWidth=child.getMeasuredWidth()+lp.leftMargin+lp.rightMargin;//子View占据的高度intchildHeight=child.getMeasuredHeight()+lp.topMargin+lp.bottomMargin;//换行if(lineWidth+childWidth>sizeWidth-getPaddingLeft()-getPaddingRight()){//对比得到最大的宽度width=Math.max(width,lineWidth);//重置lineWidthlineWidth=childWidth;//记录行高height+=lineHeight;lineHeight=childHeight;}else//未换行{//叠加行宽lineWidth+=childWidth;//得到当前行最大的高度lineHeight=Math.max(lineHeight,childHeight);}//最后一个控件if(i==cCount-1){width=Math.max(lineWidth,width);height+=lineHeight;}}setMeasuredDimension(modeWidth==MeasureSpec.EXACTLY?sizeWidth:width+getPaddingLeft()+getPaddingRight(),modeHeight==MeasureSpec.EXACTLY?sizeHeight:height+getPaddingTop()+getPaddingBottom()//);}/***存储所有的View*/privateList<List<View>>mAllViews=newArrayList<List<View>>();/***每一行的高度*/privateList<Integer>mLineHeight=newArrayList<Integer>();@OverrideprotectedvoidonLayout(booleanchanged,intl,intt,intr,intb){mAllViews.clear();mLineHeight.clear();//当前ViewGroup的宽度intwidth=getWidth();intlineWidth=0;intlineHeight=0;List<View>lineViews=newArrayList<View>();intcCount=getChildCount();for(inti=0;i<cCount;i++){Viewchild=getChildAt(i);MarginLayoutParamslp=(MarginLayoutParams)child.getLayoutParams();intchildWidth=child.getMeasuredWidth();intchildHeight=child.getMeasuredHeight();//如果需要换行if(childWidth+lineWidth+lp.leftMargin+lp.rightMargin>width-getPaddingLeft()-getPaddingRight()){//记录LineHeightmLineHeight.add(lineHeight);//记录当前行的ViewsmAllViews.add(lineViews);//重置我们的行宽和行高lineWidth=0;lineHeight=childHeight+lp.topMargin+lp.bottomMargin;//重置我们的View集合lineViews=newArrayList<View>();}lineWidth+=childWidth+lp.leftMargin+lp.rightMargin;lineHeight=Math.max(lineHeight,childHeight+lp.topMargin+lp.bottomMargin);lineViews.add(child);}//forend//处理最后一行mLineHeight.add(lineHeight);mAllViews.add(lineViews);//设置子View的位置intleft=getPaddingLeft();inttop=getPaddingTop();//行数intlineNum=mAllViews.size();for(inti=0;i<lineNum;i++){//当前行的所有的ViewlineViews=mAllViews.get(i);lineHeight=mLineHeight.get(i);for(intj=0;j<lineViews.size();j++){Viewchild=lineViews.get(j);//判断child的状态if(child.getVisibility()==View.GONE){continue;}MarginLayoutParamslp=(MarginLayoutParams)child.getLayoutParams();intlc=left+lp.leftMargin;inttc=top+lp.topMargin;intrc=lc+child.getMeasuredWidth();intbc=tc+child.getMeasuredHeight();//为子View进行布局child.layout(lc,tc,rc,bc);left+=child.getMeasuredWidth()+lp.leftMargin+lp.rightMargin;}left=getPaddingLeft();top+=lineHeight;}}/***与当前ViewGroup对应的LayoutParams*/@OverridepublicLayoutParamsgenerateLayoutParams(AttributeSetattrs){returnnewMarginLayoutParams(getContext(),attrs);}}

流式布局代码实现的注释还算比较详细,请参考具体代码及注释说明。

流式布局xml文件

<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"><com.sunny.flowlayout.view.FlowLayoutandroid:id="@+id/id_flowlayout"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#E5E5F5"android:padding="20dp"></com.sunny.flowlayout.view.FlowLayout></RelativeLayout>

主页面Activity的实现

packagecom.sunny.flowlayout;importcom.sunny.flowlayout.view.FlowLayout;importandroid.R.mipmap;importandroid.os.Bundle;importandroid.app.ActionBar.LayoutParams;importandroid.app.Activity;importandroid.view.LayoutInflater;importandroid.view.Menu;importandroid.view.ViewGroup.MarginLayoutParams;importandroid.widget.Button;importandroid.widget.TextView;publicclassFlowLayoutActivityextendsActivity{privateFlowLayoutmFlowLayout;privateString[]mVals=newString[]{"Hello","Android","Welcome","Music","Sport","Working","Game","Fishing","Shopping","MusicSinging","Sporthappy","WorkingHard","GameTeam","Fishingriver","Shoppingmore"};@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_flow_layout);mFlowLayout=(FlowLayout)findViewById(R.id.id_flowlayout);initData();}//初始化数据publicvoidinitData(){LayoutInflatermInflater=LayoutInflater.from(this);for(inti=0;i<mVals.length;i++){TextViewtv=(TextView)mInflater.inflate(R.layout.tv,mFlowLayout,false);tv.setText(mVals[i]);mFlowLayout.addView(tv);}}}

TextView布局xml文件

<?xmlversion="1.0"encoding="utf-8"?><TextViewxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="HelloWorld"android:background="@drawable/textview_bg"android:layout_margin="5dp"android:textColor="#5BC4ED"></TextView>

TextView设置背景样式

<?xmlversion="1.0"encoding="utf-8"?><shapexmlns:android="http://schemas.android.com/apk/res/android"><solidandroid:color="#ffffff"/><cornersandroid:radius="5dp"/><paddingandroid:top="2dp"android:left="10dp"android:right="10dp"android:bottom="2dp"/></shape>

今天是第一次写博客,今天是开始,我会一直坚持下去,欢迎大家一块交流学习

更多相关文章

  1. Android之UI学习篇七:ImageView实现适屏和裁剪图片的功能
  2. Android之UI学习篇七:ImageView实现适屏和裁剪图片的功能
  3. Android实现九宫格
  4. Android实现九宫格
  5. Android中获取屏幕相关信息(屏幕大小,状态栏、标题栏高度)
  6. Android(安卓)getMeasuredHeight()与getHeight()的区别
  7. android滑动view
  8. Android动态生成RadioButton
  9. Android(安卓)侧滑删除功能

随机推荐

  1. 常用的报表工具有哪些_目前最流行的报表
  2. 国外有Tableau,国内有思迈特软件Smartbi
  3. 应用计量经济学现状: 因果推断与政策评估
  4. iOS发开之如何成为一名高手?
  5. python+opencv实现连通区域分离
  6. Linux运维入门教程06-01 (系统的初始化和
  7. Python关于 物理实验数据的代码简化处理
  8. 索引不是越多越好,理解索引结构原理,才有助
  9. Python中的图像增强技术
  10. 基于Logstash+Zabbix4.4做主机登录失败监