android流式布局热门标签的实现
16lz
2021-12-04
在日常的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>
今天是第一次写博客,今天是开始,我会一直坚持下去,欢迎大家一块交流学习
更多相关文章
- Android之UI学习篇七:ImageView实现适屏和裁剪图片的功能
- Android之UI学习篇七:ImageView实现适屏和裁剪图片的功能
- Android实现九宫格
- Android实现九宫格
- Android中获取屏幕相关信息(屏幕大小,状态栏、标题栏高度)
- Android(安卓)getMeasuredHeight()与getHeight()的区别
- android滑动view
- Android动态生成RadioButton
- Android(安卓)侧滑删除功能