基礎文章地址: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">大概就是這些了 好久沒寫博客了 不知道還能堅持到多久
新聞熱點
疑難解答