android自定義viewgroup之我也玩瀑布流


先看效果圖吧,

繼上一篇《android自定義viewgroup實現等分格子布局》中實現的布局效果,這里稍微有些區別,每個格子的高度不規則,就是傳說的瀑布流布局,一般實現這種效果,要么用第三方控件,如果不是加載圖片還可以直接寫在xml中實現,不過代碼會很多的;

下面我重寫了viewgroup,實現onMeasure,onLayout方法,動態設置每個布局的高度,這里有一個小的技巧,一般我們自定義的控件,嵌套在scrollview中顯示不全,這個問題也糾結我一小會,不過當你打開scrollview的源碼,你會發現有一個地方,同時可以理解scrollview中嵌套viewpager,gridview,listview時候會顯示不全的問題

下面是自定義viewgroup的全部代碼:

package com.allen.view;

import com.allen.mygridlayout.R;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.MeasureSpec;

/**
 * @package:com.fumei.letao.views
 * @author:Allen
 * @email:jaylong1302@163.com
 * @data:2013年11月26日 下午8:39:51
 * @description:瀑布流視圖
 */
public class WaterfullLayout extends ViewGroup {

    final String tag = "balance";

    // 列數
    int columns = 2;
    // 行數
    int rows = 0;
    // 邊距
    int margin = 10;
    // 子視圖數量
    int count = 0;
    private int mMaxChildWidth = 0;
    private int mMaxChildHeight = 0;

    public WaterfullLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        if (attrs != null) {
            TypedArray a = getContext().obtainStyledAttributes(attrs,
                    R.styleable.MyGridLayout);
            columns = a.getInteger(R.styleable.MyGridLayout_numColumns, 2);
            margin = (int) a.getInteger(R.styleable.MyGridLayout_itemMargin, 2);
        }
    }

    public WaterfullLayout(Context context, AttributeSet attrs) {
        super(context, attrs, 0);
        // TODO Auto-generated constructor stub
    }

    public WaterfullLayout(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        mMaxChildWidth = 0;
        mMaxChildHeight = 0;

        count = getChildCount();
        if (count == 0) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }
        rows = count % columns == 0 ? count / columns : count / columns + 1;// 行數
        int top[] = new int[columns];
        for (int i = 0; i < rows; i++) {// 遍歷行
            for (int j = 0; j < columns; j++) {// 遍歷每一行的元素
                View child = this.getChildAt(i * columns + j);
                if (child == null)
                    break;
                ViewGroup.LayoutParams lp = child.getLayoutParams();

                if (child.getVisibility() == GONE) {
                    continue;
                }

                child.measure(MeasureSpec.makeMeasureSpec(
                        MeasureSpec.getSize(widthMeasureSpec),
                        MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
                        lp.height, MeasureSpec.AT_MOST));
                top[j] += lp.height + margin;
                mMaxChildWidth = Math.max(mMaxChildWidth,
                        child.getMeasuredWidth());
            }

        }

        setMeasuredDimension(resolveSize(mMaxChildWidth, widthMeasureSpec),
                resolveSize(getMax(top) + margin, heightMeasureSpec));

    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // TODO Auto-generated method stub
        int height = b - t;// 布局區域高度
        int width = r - l;// 布局區域寬度

        if (count == 0)
            return;

        int gridW = (width - margin * (columns + 1)) / columns;// 格子寬度
        int gridH = 0;// 格子高度

        int left = 0;
        int top[] = new int[columns];

        for (int i = 0; i < rows; i++) {// 遍歷行
            for (int j = 0; j < columns; j++) {// 遍歷每一行的元素
                View child = this.getChildAt(i * columns + j);
                if (child == null)
                    return;
                ViewGroup.LayoutParams lp = child.getLayoutParams();

                child.measure(MeasureSpec.makeMeasureSpec(gridW,
                        MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
                        lp.height, MeasureSpec.AT_MOST));

                // 如果最后有一個對其的標志,為了底部對其
                if (child.getTag() != null && child.getTag().equals(tag)) {
                    child.measure(MeasureSpec.makeMeasureSpec(gridW,
                            MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
                            getMax(top) - top[j], MeasureSpec.EXACTLY));
                    gridH = getMax(top) - top[j];
                    left = j * gridW + margin * (j + 1);
                    child.layout(left, top[j] + margin, left + gridW, top[j]
                            + gridH);
                    break;
                }

                gridH = lp.height;
                left = j * gridW + margin * (j + 1);
                top[j] += margin;
                child.layout(left, top[j], left + gridW, top[j] + gridH);
                top[j] += gridH;
            }

        }
    }

    /** 計算整體布局高度,為了在嵌套在scrollview中能顯示出來 */
    private int getMax(int array[]) {
        int max = array[0];
        for (int i = 0; i < array.length; i++) {
            if (max < array[i])
                max = array[i];
        }
        return max;
    }

}
View Code

所有demo工程點擊這里下載:click me!!!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM