流式布局FlowLayout


public class FlowLayout extends ViewGroup {
    private int mHorizonalSpace=8;
    private int mVerticalSpace=8;
    /** 當(dāng)前的流式布局不確定有幾行,可能有多行也可能沒有行.**/
    private List<Line> mLines=new ArrayList<Line>();
    private int mContainerWidth;
    private int mContainerHeight;
    /***
    行對象
    */
    private class Line
    {
        private int lineWidth=0;
        private int lineHeight=0;
        /**存放行的元素 **/
        private List<View> views=new ArrayList<View>();
        public int getLineWidth() {
            return lineWidth;
        }
        public int getLineHeight() {
            return lineHeight;
        }
        public List<View> getViews() {
            return views;
        }
        
        // 還需要支持往行里面添加元素
        public void addChild(View view) {
            // 如果當(dāng)前行不存在這個元素的話就把元素添加進來
            if (!views.contains(view)) {
                
                // 測量
                view.measure(0, 0);
                if (views.size() ==0) {
                    // 當(dāng)前只有一個元素的,寬與高就由它決定
                    lineWidth += view.getMeasuredWidth() + mHorizonalSpace;
                    lineHeight = view.getHeight();
                } else {
                    // 有不同高度的元素
                    lineWidth += view.getMeasuredWidth() + mHorizonalSpace;
                    lineHeight = Math.max(lineHeight, view.getMeasuredHeight());
                }
                views.add(view);
            }
        }
    }
    public FlowLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }
    /**.xml  畫頁面, 所見即所得 */
    public FlowLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }
    /**.java  new FlowLayout(context)  動態(tài)輸出*/
    public FlowLayout(Context context) {
        super(context);
        init(context);
    }

    /*** 方法
    @param context
    */
    private void init(Context context) {
        //setBackgroundColor(Color.BLUE);
    
    }
    /*** 方法  一懈贺。測量
    @param widthMeasureSpec
    @param heightMeasureSpec
    */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        mLines.clear();
        // 一弄抬。容器它是占滿屏幕
        
        mContainerWidth = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
        
        // 二。高度是由行數(shù)決定茬故, 所以針對所有控件進行測量寬高,分行就可以算出行數(shù)了.
        int childCount = getChildCount();
        Line currLine = null;
        for (int i = 0; i < childCount; i++) {
            // 獲取每個元素
            View child = getChildAt(i);
            // 測寬高
            child.measure(0, 0);
            int cHeight = child.getMeasuredHeight();
            int cWidth = child.getMeasuredWidth();
            //為第一個元素創(chuàng)建行
            if (mLines.size() == 0) {
                // 新建一行
                currLine = new Line();
                mLines.add(currLine);
            }
            //如果未滿一行往里添加
            int remainWidth = mContainerWidth - currLine.getLineWidth();
            if (remainWidth >=cWidth) {
                currLine.addChild(child);
            } else {//存放空間不夠再新建一行
                currLine = new Line();
                mLines.add(currLine);
                currLine.addChild(child);
            }
        }
        //累加高度
        
        mContainerHeight = 0;
        
        for (int i = 0; i < mLines.size(); i++) {
            if (i != (mLines.size() - 1)) {
                mContainerHeight += mLines.get(i).getLineHeight() + mVerticalSpace;
            } else {
                mContainerHeight += mLines.get(i).getLineHeight();
            }
        }
        // 使用包裹內(nèi)容的方式式把每一個元素計算出容器的寬與高,設(shè)置給當(dāng)前容器
        setMeasuredDimension(mContainerWidth, mContainerHeight);
    }
    /*** 方法 二。擺放  left top bottom right 
    @param changed
    @param l
    @param t
    @param r
    @param b
    */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        int lineLeft=0;
        int lineTop=0;
        for(int i=0;i<mLines.size();i++)
        {
            
            Line line = mLines.get(i);
            int eachViewSpace=(mContainerWidth-line.getLineWidth())/line.getViews().size();
            //容器空間
            if(i>0)
            {
                //第二行開始top要累加
                lineTop+=mLines.get(i-1).getLineHeight()+mVerticalSpace;
            }
            //對每一行中的元素進行擺放
            List<View> views = line.getViews();
            lineLeft=0;
            for(int index=0;index<views.size();index++)
            {
                //把里面的每一個
                View lineChild = views.get(index);
                if (index > 0) {
                    // 本行中的第二個元素
                    lineLeft = views.get(index - 1).getRight() + mHorizonalSpace;
                }
                int cWidth = lineChild.getMeasuredWidth();
                int cHeight = lineChild.getMeasuredHeight();
                int mode=MeasureSpec.EXACTLY;//80+10 andoid_layoutWidth="90dp"
                //創(chuàng)建measure使用數(shù)值的方式 MODE+SIZE
                int measureWidth=MeasureSpec.makeMeasureSpec(cWidth+eachViewSpace, mode);
                lineChild.measure(measureWidth, 0);//0代表使用包裹獲取寬高
                //擺放
                int cLeft=lineLeft;
                int cTop=lineTop;
                int cRight=cLeft+cWidth+eachViewSpace;
                int cBottom=cTop+cHeight;
                lineChild.layout(cLeft, cTop, cRight, cBottom);
            }
        }
    }
    /*** 方法 三。畫圖,一般不去重寫
    @param canvas
    */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }

}



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末焰手,一起剝皮案震驚了整個濱河市逆瑞,隨后出現(xiàn)的幾起案子荠藤,更是在濱河造成了極大的恐慌,老刑警劉巖获高,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哈肖,死亡現(xiàn)場離奇詭異,居然都是意外死亡念秧,警方通過查閱死者的電腦和手機淤井,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來摊趾,“玉大人币狠,你說我怎么就攤上這事±悖” “怎么了漩绵?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長肛炮。 經(jīng)常有香客問我止吐,道長,這世上最難降的妖魔是什么侨糟? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任碍扔,我火速辦了婚禮,結(jié)果婚禮上粟害,老公的妹妹穿的比我還像新娘蕴忆。我一直安慰自己,他們只是感情好悲幅,可當(dāng)我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布套鹅。 她就那樣靜靜地躺著,像睡著了一般汰具。 火紅的嫁衣襯著肌膚如雪卓鹿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天留荔,我揣著相機與錄音吟孙,去河邊找鬼澜倦。 笑死,一個胖子當(dāng)著我的面吹牛杰妓,可吹牛的內(nèi)容都是我干的藻治。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼巷挥,長吁一口氣:“原來是場噩夢啊……” “哼桩卵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起倍宾,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤雏节,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后高职,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钩乍,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年怔锌,在試婚紗的時候發(fā)現(xiàn)自己被綠了寥粹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡埃元,死狀恐怖排作,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情亚情,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布哈雏,位于F島的核電站楞件,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏裳瘪。R本人自食惡果不足惜土浸,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望彭羹。 院中可真熱鬧黄伊,春花似錦、人聲如沸派殷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽毡惜。三九已至拓轻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間经伙,已是汗流浹背扶叉。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人枣氧。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓溢十,卻偏偏與公主長得像,于是被迫代替她去往敵國和親达吞。 傳聞我的和親對象是個殘疾皇子张弛,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容