基础文章地址:http://blog.csdn.net/lmj623565791/article/details/38352503 感谢大神文章
因为要做那种流式布局标签,查了很多资料,都是大同小异。
有些没有解决FlowLayout的padding
的问题。很多都是直接转载的,而且FlowLayout里面的间隔都是靠子view的margin
来解决,感觉很不科学。所以自己的就在这个基础的封装自己的流式布局XFlowLayout自定义的水平间隔hgap和垂直间隔vgap
整个类都有注释,理解应该不困难
里面主要的就是onMeasure和onLayout方法,需要知道测量布局的三种模式,后面直接添加view就好
废话不多了,直接上代码
主要类:
public class XFlowLayout extends ViewGroup { //所有的子view PRivate List<List<View>> mAllChildViews = new ArrayList<>(); //每一行的高度 private List<Integer> mLineHeight = new ArrayList<>(); //水平和垂直间距 private int hgap; private int vgap; public XFlowLayout(Context context) { this(context, null); } public XFlowLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public XFlowLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ZBJFlowLayout); hgap = (int) ta.getDimension(R.styleable.ZBJFlowLayout_hgap, 0); vgap = (int) ta.getDimension(R.styleable.ZBJFlowLayout_vgap, 0); ta.recycle(); } //测量整个布局多大 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //测量宽度和测量宽度模式 int sizeWidth = MeasureSpec.getSize(widthMeasureSpec); int modeWidth = MeasureSpec.getMode(widthMeasureSpec); //测量高度和测量高度模式 int sizeHeight = MeasureSpec.getSize(heightMeasureSpec); int modeHeight = MeasureSpec.getMode(heightMeasureSpec); //宽度和高度 int width = 0; int height = 0; //行宽和行高 int lineWidth = 0; int lineHeight = 0; //子view个数 int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); measureChild(child, widthMeasureSpec, heightMeasureSpec); //获得子view的宽高 int childWidth = child.getWidth(); int childHeight = child.getHeight(); if (lineWidth + childWidth > sizeWidth - getPaddingLeft() - getPaddingRight()) {//换行 //对比最大宽度 width = Math.max(width, lineWidth); //换行加上垂直间隔 height += lineHeight + vgap; //已经换行宽高重置 lineWidth = childWidth; lineHeight = childHeight; } else {//不换行 //不换行水平宽度加上水平间隔 lineWidth += childWidth + hgap; //对比最大高度 lineHeight = Math.max(lineHeight, childHeight); } //最后一个控件 if (i == childCount - 1) { width = Math.max(width, lineWidth); height += lineHeight; } setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width + getPaddingLeft() + getPaddingRight(), modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height + getPaddingTop() + getPaddingBottom()); } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { mAllChildViews.clear(); mLineHeight.clear(); //获得当前布局的宽度 int width = getWidth(); int lineWidth = 0; int lineHeight = 0; List<View> lineViews = new ArrayList<View>(); int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); int childWidth = child.getMeasuredWidth(); int childHeight = child.getMeasuredHeight(); if (childWidth + lineWidth > width - getPaddingLeft() - getPaddingRight()) {//换行 //记录行高 mLineHeight.add(lineHeight); //记录当前行的子view mAllChildViews.add(lineViews); //重置行宽高 lineWidth = 0; lineHeight = childHeight + vgap; //new一个新的集合 lineViews = new ArrayList<>(); } lineWidth = lineWidth + childWidth + hgap; lineHeight = Math.max(lineHeight, childHeight); lineViews.add(child); } //处理最后一行 mLineHeight.add(lineHeight); mAllChildViews.add(lineViews); //记录view位置和行数 int left = getPaddingLeft(); int top = getPaddingTop(); int lineCount = mAllChildViews.size(); for (int i = 0; i < lineCount; i++) { //当前行所有的VIEW lineViews = mAllChildViews.get(i); //当前行高 lineHeight = mLineHeight.get(i); for (int j = 0; j < lineViews.size(); j++) { View child = lineViews.get(j); if (child.getVisibility() == View.GONE) {//不显示则跳出 continue; } int cLeft = left; int cTop; if (i == 0) { cTop = top; } else { cTop = top + vgap; } int cRight = cLeft + child.getMeasuredWidth(); int cBottom = cTop + child.getMeasuredHeight(); child.layout(cLeft, cTop, cRight, cBottom); left += child.getMeasuredWidth() + hgap; } left = getPaddingLeft(); if (i == lineCount - 1) { top += lineHeight + vgap; } else { top += lineHeight; } } }// @Override// public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {// return new MarginLayoutParams(getContext(),attrs);// }}attrs文件<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="ZBJFlowLayout"> <attr name="hgap" format="dimension" /> <attr name="vgap" format="dimension" /> </declare-styleable></resources>xml里面引用<com.expect.view.XFlowLayout android:layout_margin="10dp" android:padding="10dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#5246" zfl:hgap="10dp" zfl:vgap="10dp">大概就是这些了 好久没写博客了 不知道还能坚持到多久
新闻热点
疑难解答