1. 程式人生 > >自定義 流式佈局實現

自定義 流式佈局實現

首先佈局得清晰--建立一個自定義控制元件 <com.example.mr.flow     android:id="@+id/ffff"     android:layout_width="match_parent"     android:layout_height="100dp"> 其次設定你自己想要的的shape佈局 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android">     <solid android:color="#666666"/>           <corners android:radius="10dp"/>           <padding     android:left="5dp"     android:right="5dp"     android:top="5dp"     android:bottom="5dp"/>  </shape> //然後開始寫你自定義的ViewGroup package com.example.mr;

import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup;

import java.util.ArrayList; import java.util.List;

/**  * Created by Mr趙 on 2017/12/2.  */

public class flow extends ViewGroup {     //儲存所有子View     private List<List<View>> mAllChildViews = new ArrayList<>();     //每一行的高度     private List<Integer> mLineHeight = new ArrayList<>();

    public flow(Context context) {         this(context, null);     }

    public flow(Context context, AttributeSet attrs) {         this(context, attrs, 0);     }

    public flow(Context context, AttributeSet attrs, int defStyleAttr) {         super(context, attrs, defStyleAttr);     }

    @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);         //如果當前ViewGroup的寬高為wrap_content的情況         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);             //測量子View的寬和高             measureChild(child, widthMeasureSpec, heightMeasureSpec);             //得到LayoutParams             MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();             //子View佔據的寬度             int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;             //子View佔據的高度             int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;             //換行時候             if (lineWidth + childWidth > sizeWidth) {                 //對比得到最大的寬度                 width = Math.max(width, lineWidth);                 //重置lineWidth                 lineWidth = childWidth;                 //記錄行高                 height += lineHeight;                 lineHeight = childHeight;             } else {//不換行情況                 //疊加行寬                 lineWidth += childWidth;                 //得到最大行高                 lineHeight = Math.max(lineHeight, childHeight);             }             //處理最後一個子View的情況             if (i == childCount - 1) {                 width = Math.max(width, lineWidth);                 height += lineHeight;             }         }         //wrap_content         setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width,                 modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height);         super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    }

    @Override     protected void onLayout(boolean changed, int l, int t, int r, int b) {         mAllChildViews.clear();         mLineHeight.clear();         //獲取當前ViewGroup的寬度         int width = getWidth();

        int lineWidth = 0;         int lineHeight = 0;         //記錄當前行的view         List<View> lineViews = new ArrayList<View>();         int childCount = getChildCount();         for (int i = 0; i < childCount; i++) {             View child = getChildAt(i);             MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();             int childWidth = child.getMeasuredWidth();             int childHeight = child.getMeasuredHeight();

            //如果需要換行             if (childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width) {                 //記錄LineHeight                 mLineHeight.add(lineHeight);                 //記錄當前行的Views                 mAllChildViews.add(lineViews);                 //重置行的寬高                 lineWidth = 0;                 lineHeight = childHeight + lp.topMargin + lp.bottomMargin;                 //重置view的集合                 lineViews = new ArrayList();             }             lineWidth += childWidth + lp.leftMargin + lp.rightMargin;             lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + lp.bottomMargin);             lineViews.add(child);         }         //處理最後一行         mLineHeight.add(lineHeight);         mAllChildViews.add(lineViews);

        //設定子View的位置         int left = 0;         int top = 0;         //獲取行數         int lineCount = mAllChildViews.size();         for (int i = 0; i < lineCount; i++) {             //當前行的views和高度             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;                 }                 MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();                 int cLeft = left + lp.leftMargin;                 int cTop = top + lp.topMargin;                 int cRight = cLeft + child.getMeasuredWidth();                 int cBottom = cTop + child.getMeasuredHeight();                 //進行子View進行佈局                 child.layout(cLeft, cTop, cRight, cBottom);                 left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;             }             left = 0;             top += lineHeight;         }

    }

    /**      * 與當前ViewGroup對應的LayoutParams      */     @Override     public LayoutParams generateLayoutParams(AttributeSet attrs) {         // TODO Auto-generated method stub

        return new MarginLayoutParams(getContext(), attrs);

    } } //寫完之後Activity中呼叫就可以 這是建立的陣列用於現實的內容 private String mNames[] = {         "硬碟螺絲","老人機","海爾冰箱",         "電視機","旅遊用品","家備小電器",         "服飾" }; 調取此方法可以使用 private void initChildViews() {     flowLayout = findViewById(R.id.ffff);     ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams(             ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);     lp.leftMargin = 5;     lp.rightMargin = 5;     lp.topMargin = 5;     lp.bottomMargin = 5;     for(int i = 0; i < mNames.length; i ++){         TextView view = new TextView(this);         view.setText(mNames[i]);         view.setTextColor(Color.WHITE);         view.setBackgroundDrawable(getResources().getDrawable(R.drawable.textview_bg));         flowLayout.addView(view,lp);     }

} 作者:黑暗中的鬼  來源:CSDN  原文:https://blog.csdn.net/Mrzhaoplus/article/details/78700539  版權宣告:本文為博主原創文章,轉載請附上博文連結!