先看看效果图:
先自定义一个类TestViewGroup,继承自ViewGroup,重写onMeasure、onLayout方法。
一、重写onMeasure方法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
1、获取该ViewGroup的尺寸信息
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
2、测量子view
measureChildren(widthMeasureSpec, heightMeasureSpec);
3、遍历子view
4、获取子view尺寸信息
5、设置每行每列的宽高信息
6、设置子view的四个顶点尺寸信息
7、最后设置setMeasuredDimension
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
//测量子View
measureChildren(widthMeasureSpec, heightMeasureSpec);
//记录总宽、总高:初始值为 -50,因为后面间距每个需要增加50
int lineWidth = -widthSpacing;
int lineHeight = -heightSpacing;
//子View的宽高
int cHeight;
int cWidth;
//遍历子View
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
//获取每个View的实际宽
cWidth = view.getMeasuredWidth();
cHeight = view.getMeasuredHeight();
if (lineWidth + cWidth > widthSize) {
//如果超出父布局,则换行,高度新增,宽度从0开始:每次竖向距离增加50
lineHeight = lineHeight + cHeight + heightSpacing;
lineWidth = -widthSpacing;
} else {
//否则使用原有的宽高
lineHeight = Math.max(lineHeight, cHeight);
}
//宽度累加:增加50间距,横向距离
lineWidth = cWidth + widthSpacing + lineWidth;
//设置边距
view.setLeft(lineWidth - cWidth);
view.setRight(lineWidth);
view.setTop(lineHeight - cHeight);
view.setBottom(lineHeight);
}
//宽高变化后进行设置
setMeasuredDimension(widthSize, lineHeight);
}
每个步骤上面有详细的步骤信息备注,上面的heightSpacing 为设置每行间距,widthSpacing为每列间距,这么默认可以设置一个默认值,也可以提供一个方法对外暴露来使用。
二、onLayout
遍历每个view逐个设置。
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View view = getChildAt(i);
if (view.getVisibility() != View.GONE) {
//逐个绘制
view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
}
}
}
三、使用
这里直接写在XML里面,也可以动态添加布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="40dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="自定义ViewGroup"
android:textColor="@android:color/black"
android:textSize="24sp"/>
<com.viewgroup.viewgroupdemo.TestViewGroup
android:id="@+id/viewgroup"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="50dp">
<TextView
style="@style/textstyle"
android:layout_height="30dp"
android:text="铁总回应高铁飙车"/>
<TextView
style="@style/textstyle"
android:text="腾讯大王卡"
/>
<TextView
style="@style/textstyle"
android:text="苹果8降价"
/>
<TextView
style="@style/textstyle"
android:text="王者荣耀6"
/>
<TextView
style="@style/textstyle"
android:background="@drawable/shape_text_bg"
android:text="张三2"
/>
…………………………………………………………………………………………………………………………………………
</com.viewgroup.viewgroupdemo.TestViewGroup>
</LinearLayout>
源代码地址:https://download.csdn.net/download/yoonerloop/10935103
今年最后一篇文章,祝大家新春快乐,万事如意!