100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 自定义流式布局

自定义流式布局

时间:2020-10-28 02:49:15

相关推荐

自定义流式布局

效果图:

先梳理下整个流程:

继承ViewGroup ,重写onMeasure,onLayout 方法;在onMeasure方法里通过加入其中的子view个数来计算父级的宽高;在onLayout 方法里对子view进行排版(横向排列),即超过父级宽度就另换一行

注意:当父级宽高发生变化时会重新执行onMeasure,onLayout 方法,即会被调用2遍。

详细代码如下:

FlowLayout:

import java.util.ArrayList;import java.util.List;import android.annotation.SuppressLint;import android.content.Context;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;/*** 自定义流式布局*/public class FlowLayout extends ViewGroup{/** view距离父布局的边界信息*/private MarginLayoutParams marginLayoutParams;/** child宽度*/private int childwidth;/** child高度*/int childheight;/** 父级实际的宽度*/int factwidth;/** 父级实际的高度*/int factheight;/** 每行宽度*/int linewidth;/** 每行高度*/int lineheight;/** 用于记录上一次的行高*/int lastchildheight=0;public FlowLayout(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}public FlowLayout(Context context, AttributeSet attrs) {super(context, attrs,0);}public FlowLayout(Context context) {super(context,null);}/*** 根据子view来确定宽高* */@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//添加了子视图后,父级视图布局会发生改变,onMeasure方法会被执行两遍factheight=0;factwidth=0;int widthsize=MeasureSpec.getSize(widthMeasureSpec);int widthmode=MeasureSpec.getMode(widthMeasureSpec);int heightsize=MeasureSpec.getSize(heightMeasureSpec);int heightmode=MeasureSpec.getMode(heightMeasureSpec);int childcount=getChildCount();for(int i=0;i<childcount;i++){View child=getChildAt(i);measureChild(child, widthMeasureSpec, heightMeasureSpec);marginLayoutParams=(MarginLayoutParams) child.getLayoutParams();childwidth=child.getMeasuredWidth()+marginLayoutParams.leftMargin+marginLayoutParams.rightMargin;childheight=child.getMeasuredHeight()+marginLayoutParams.topMargin+marginLayoutParams.bottomMargin;//如果child的宽度和加起来大于了父级宽度,则计算最大值,并作为父级实际宽度if(linewidth+childwidth>widthsize){//计算父级宽度factwidth=Math.max(widthsize,linewidth);//计算父级高度factheight+=lastchildheight;//重置行宽linewidth=0;//重置行高lastchildheight=0;lineheight=0;}linewidth+=childwidth;//取最大行高(用于应对特殊字体大小)lineheight=Math.max(lastchildheight,childheight);lastchildheight=lineheight;//特殊情况,处理最后一个child(有可能该行只有一个view,也可能最后一个view刚好处于最后一行最后位置)if(i==childcount-1){factwidth=Math.max(widthsize,linewidth);factheight+=lastchildheight;lastchildheight=0;lineheight=0;linewidth=0;}}//把测量结果设置为父级宽高setMeasuredDimension(widthmode==MeasureSpec.EXACTLY?widthsize:factwidth,heightmode==MeasureSpec.EXACTLY?heightsize:factheight);}/** 每行view的集合*/private List<List<View>> AllChildView=new ArrayList<List<View>>();/** 每行高度的集合*/private List<Integer> LineHeight=new ArrayList<Integer>();/*** 排版 (横向排列)* */@SuppressLint("DrawAllocation")@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {factwidth=getMeasuredWidth();AllChildView.clear();LineHeight.clear();List<View> linelist=new ArrayList<View>();//计算每行可以放view的个数,并放进集合int childcount=getChildCount();for(int i=0;i<childcount;i++){View view=getChildAt(i);marginLayoutParams=(MarginLayoutParams) view.getLayoutParams();int childwidth=view.getMeasuredWidth()+marginLayoutParams.leftMargin+marginLayoutParams.rightMargin;int childheight=view.getMeasuredHeight()+marginLayoutParams.topMargin+marginLayoutParams.bottomMargin;//每行子view加起来的宽度大于父级宽度 就把该行子view集合放进所有行的集合里if(linewidth+childwidth>=factwidth){LineHeight.add(lastchildheight);//行高集合AllChildView.add(linelist);//行数集合//重置linewidth=0;lastchildheight=0;//重新创建一个集合linelist=new ArrayList<View>();}//取每行的最大高度lineheight=Math.max(childheight,lastchildheight);lastchildheight=lineheight;linewidth+=childwidth;//每行的view集合linelist.add(view);//如果最后一行没有大于父级宽度,需要特殊处理if(i==childcount-1){LineHeight.add(lastchildheight);//行高集合AllChildView.add(linelist);//行数集合lastchildheight=0;linewidth=0;}}int left=0;int top=0;//设置子view的位置for(int w=0;w<AllChildView.size();w++){//总共多少行linelist=AllChildView.get(w);lineheight=LineHeight.get(w);for(int m=0;m<linelist.size();m++){//每行排版View childview=linelist.get(m);//隐藏状态的子view不参与排版if(childview.getVisibility()==View.GONE){continue;}marginLayoutParams=(MarginLayoutParams) childview.getLayoutParams();int cleft=left+marginLayoutParams.leftMargin;int ctop=top+marginLayoutParams.topMargin+(lineheight/2-childview.getHeight()/2);int cright=cleft+childview.getMeasuredWidth();int cbottom=ctop+childview.getMeasuredHeight();childview.layout(cleft, ctop, cright, cbottom);left+=childview.getMeasuredWidth()+marginLayoutParams.leftMargin+marginLayoutParams.rightMargin;}//每行排完之后重新设置属性left=0;top+=lineheight;}}// @Override// public LayoutParams generateLayoutParams(AttributeSet attrs) {//return new MarginLayoutParams(getContext(), attrs);// }}

FlowLayoutActivity:

import java.util.Random;import android.app.Activity;import android.graphics.Color;import android.os.Bundle;import android.view.Gravity;import android.view.ViewGroup.LayoutParams;import android.view.ViewGroup.MarginLayoutParams;import android.widget.TextView;public class FlowLayoutActivity extends Activity {private String mNames[] = {"welcome","android","TextView","apple","jamy","kobe bryant","jordan","layout","viewgroup","margin","padding","text","地方了开始讲道理","第三方","的飞洒","name","type","search","logcat","逗你玩","罚款圣诞节疯狂绝对是垃圾分类看见冻死了快解放了跨世纪的离开房间了少打飞放得开收垃圾费考虑到就是浪费","发神经"};private Random random;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_flow_layout);random=new Random();init();}private void init() {FlowLayout flowLayout=(FlowLayout) findViewById(R.id.flowlayout);MarginLayoutParams lp = new MarginLayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);lp.leftMargin = 5;lp.rightMargin = 5;lp.topMargin = 5;lp.bottomMargin = 5;int a=0,i=0;while(a<40){++a;i=random.nextInt(mNames.length);TextView view = new TextView(this);view.setText(mNames[i]);view.setTextColor(Color.WHITE);view.setGravity(Gravity.CENTER);view.setBackground(getResources().getDrawable(R.drawable.textview_bg));if(i%3==0){view.setTextSize(20);}view.setTextColor(Color.rgb(random.nextInt(255), random.nextInt(255), random.nextInt(255)));flowLayout.addView(view,lp);}}}

R.layout.activity_flow_layout:

<LinearLayout xmlns:android="/apk/res/android"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context="com.example.mytoolutils.FlowLayoutActivity" ><com.example.mytoolutils.FlowLayoutandroid:id="@+id/flowlayout"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@android:color/holo_blue_light" ></com.example.mytoolutils.FlowLayout></LinearLayout>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。