(小白秒懂)自定义ViewGroup之瀑布流布局

先说说我这里说的瀑布流布局指的是什么:

  • 就是有N个TextView,或者其他的View,依次排列开,和LinearLayout不同的是,可以换行
    看看图吧,否则想不到,图片如下:
    这里写图片描述

不用多想,肯定没有现成的View去使用,因为你也不知道一行有多少个,都是根据这个View的宽度自己去排列的。所以我们使用ViewGroup去自定义。

public class MyGridView extends ViewGroup {

    private int interval = 50;//间隔,为了看着方便写的,实际中使用padding

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

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

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

    //好多的时候我们不知道什么时候使用getMeasuredHeight()或者getHeight(),如果不想去看源码,那就记住了:在setMeasuredDimension()方法之后getMeasuredHeight()就有值了,而getHeight()只有在layout之后才有值。
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//这个是比较常见的onmeasure方法下确定view宽和高的方法,它的参数是由父布局传递给子布局的,
        Log.e("----------", "onMeasure:");
        //onMeasure会被回调两次,所以这个值最好为局部的
        int mWidth = 0, mHeight = 0;
        //该方法触发所有子View的onMeasure函数去测量宽高,即getMeasuredHeight方法可以获取子View的宽高,别急上面的结论没被推翻,因为根据源码measureChildren最后可以追踪到setMeasuredDimension()方法函数,如果不调用该方法,在onLayout中childview.getMeasuredHeight()也无法获得值。
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        //MeasureSpec封装了父View传递给子View的布局要求,即mode和size
        int wSize = MeasureSpec.getSize(widthMeasureSpec);

        //通过子View高度计算父view的高度
        for (int i = 0; i < getChildCount(); i++) {
            Log.e("----------", "i:" + i + ",mWidth:" + mWidth);
            View childView = getChildAt(i);
            if (mWidth + interval + childView.getMeasuredWidth() > wSize) {
                mHeight = (mHeight + interval + childView.getMeasuredHeight());
                Log.e("----------", "mHeight:" + mHeight);
                mWidth = 0;
            }
            mWidth = mWidth + interval + childView.getMeasuredWidth();
            //最后一行的高度要加上,有更好办法的欢迎补刀
            if (i == getChildCount() - 1) {
                if (mWidth > 0 && mWidth < wSize) {
                    mHeight = mHeight+childView.getMeasuredHeight()+interval;
                    Log.e("----------", "mHeight:" + mHeight);
                }
            }
        }
        //设置ViewGroup的宽高
        setMeasuredDimension(wSize, mHeight);
        Log.e("----------", "----------------");
    }

    //一个一个的布局就可以了,只需要控制换行
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int currentx = 0;
        int currenty = 0;
        for (int i = 0; i < getChildCount(); i++) {

            View childView = getChildAt(i);

            if (currentx + childView.getMeasuredWidth() > getWidth()) {
                currenty = (currenty + interval + childView.getMeasuredHeight());
                currentx = 0;
            }
            childView.layout(currentx, currenty, currentx + childView.getMeasuredWidth(), currenty + childView.getMeasuredHeight());
            currentx = currentx + interval + childView.getMeasuredWidth();
        }
    }

    //这个方法可以不实现,因为我们没有重绘东西,只是把View重新排列了一遍
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }
}

接下来看看布局吧:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.a_0102.mylearn.gesture.GesturePwdActivity">
    <!--一定要用全名,即包名+类名-->
    <com.example.a_0102.mylearn.view.MyGridView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/blue">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="哈哈哈" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="患得患失绝代风华觉得好烦" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="好多好多好多" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜呜" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="的奋斗奋斗奋斗" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text=" 多的点点滴滴" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="哈哈哈"
            android:background="@color/colorAccent"/>
    </com.example.a_0102.mylearn.view.MyGridView>

</LinearLayout>

猜你喜欢

转载自blog.csdn.net/hello_1s/article/details/81097492