先说说我这里说的瀑布流布局指的是什么:
- 就是有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>