Let's talk about what I mean by waterfall layout here:
- There are N textviews, or other views, arranged one by one. Unlike LinearLayout, you can wrap lines
Take a look at the picture. Otherwise, it's unexpected. The picture is as follows:
Don't think about it. There must be no existing View to use, because you don't know how many lines there are. They are all arranged according to the width of the View. So we use ViewGroup to customize it.
public class MyGridView extends ViewGroup {
private int interval = 50;//In order to read and write conveniently, padding is used in practice
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);
}
//A lot of times, we don't know when to use getMeasuredHeight() or getHeight(). If you don't want to see the source code, remember: after the setMeasuredDimension() method, getMeasuredHeight() has a value, while getHeight() has a value only after the layout.
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//This is a common method to determine the view width and height under onmeasure. Its parameters are passed from the parent layout to the child layout,
Log.e("----------", "onMeasure:");
//onMeasure will be called back twice, so this value is better to be local
int mWidth = 0, mHeight = 0;
//This method triggers the onMeasure function of all child views to measure the width and height, that is, the getMeasuredHeight method can get the width and height of child views. Don't worry, the above conclusion has not been overturned, because according to the source measureChildren, the setMeasuredDimension() method function can be traced finally. If this method is not called, childview.getMeasuredHeight() in onLayout can't get the value.
measureChildren(widthMeasureSpec, heightMeasureSpec);
//MeasureSpec encapsulates the layout requirements passed from the parent View to the child View, namely mode and size
int wSize = MeasureSpec.getSize(widthMeasureSpec);
//Calculate the height of the parent view from the height of the child 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();
//The height of the last line should be added. There is a better way to welcome mending
if (i == getChildCount() - 1) {
if (mWidth > 0 && mWidth < wSize) {
mHeight = mHeight+childView.getMeasuredHeight()+interval;
Log.e("----------", "mHeight:" + mHeight);
}
}
}
//Set the width and height of the ViewGroup
setMeasuredDimension(wSize, mHeight);
Log.e("----------", "----------------");
}
//One by one layout is OK, just control line feed
@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();
}
}
//This method can't be implemented, because we didn't redraw things, just rearranged the View
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
}
Let's take a look at the layout:
<?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">
<!--Be sure to use the full name, i.e. package name+Class name-->
<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="Ha ha ha" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="I'm so worried about success and loss" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Many, many, many" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Sobbing sobbing sobbing sobbing sobbing sobbing sobbing sobbing sobbing" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Struggle and struggle" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text=" More and more" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Ha ha ha"
android:background="@color/colorAccent"/>
</com.example.a_0102.mylearn.view.MyGridView>
</LinearLayout>