一、来张图片看看实现的效果
二、上代码
1、布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:layout_marginRight="6dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#e8e8e8"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:paddingRight="10dp"
android:paddingBottom="6dp"
android:textColor="#000000" />
</LinearLayout>
2、自定义流布局
public class FlowLayout extends ViewGroup {
private LayoutInflater mInflater;
public FlowLayout(Context context) {
this(context, null);
}
public FlowLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public FlowLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mInflater = LayoutInflater.from(getContext());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
int count = getChildCount();
int lineWidth = 0;
int topHeight = 0;
int maxWidth = 0;
int paddingLeft = getPaddingLeft();
int paddingRight = getPaddingRight();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
// 测量子View的宽和高
measureChild(child, widthMeasureSpec, heightMeasureSpec);
// 得到LayoutParams
MarginLayoutParams lp = (MarginLayoutParams) child
.getLayoutParams();
// 子view的占据的宽度
int childWidth = child.getMeasuredWidth() + lp.leftMargin
+ lp.rightMargin;
// 子view占据的高度
int childHeight = child.getMeasuredHeight() + lp.topMargin
+ lp.bottomMargin;
if (lineWidth + childWidth > sizeWidth - paddingLeft - paddingRight) {
//换行
lineWidth = childWidth;
topHeight += childHeight;
//确保始终得到最大的宽度
maxWidth = Math.max(maxWidth, lineWidth);
} else {
lineWidth += childWidth;
//确保始终得到最大的宽度
maxWidth = Math.max(maxWidth, lineWidth);
}
//最后一个
if (i == count - 1) {
topHeight += childHeight;
}
}
setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth
: maxWidth + paddingLeft + paddingRight,
modeHeight == MeasureSpec.EXACTLY ? sizeHeight : topHeight
+ getPaddingTop() + getPaddingBottom());
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int paddingLeft = getPaddingLeft();
int paddingRight = getPaddingRight();
int paddingTop = getPaddingTop();
int width = getWidth();
int lastLineTop = 0;
int lastRight = 0;
int lastBottom = 0;
boolean firstLine=true;
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
MarginLayoutParams lp = (MarginLayoutParams) child
.getLayoutParams();
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
int left = 0;
int top = 0;
int right = 0;
int bottom = 0;
if (lastRight+childWidth+lp.rightMargin > width + paddingRight) {
//换行
left = paddingLeft + lp.leftMargin;
top = lastBottom + lp.topMargin;
lastLineTop=lastBottom;
firstLine=false;
} else {
//未换行
left = lastRight + lp.leftMargin;
if(firstLine){
top = paddingTop + lp.topMargin;
}else {
top = lastLineTop+lp.topMargin;
}
}
right = left + childWidth + lp.rightMargin;
bottom = top + childHeight + lp.bottomMargin;
// 为子view布局
child.layout(left, top, right, bottom);
lastRight = right;
lastBottom = bottom;
}
}
/**
* 默认返回的LayoutParams
*/
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
public void initData(List<String> list) {
int count = list.size();
for (int i = 0; i < count; i++) {
View view = mInflater.inflate(R.layout.fl_tv, this,
false);
final TextView tv = (TextView) view.findViewById(R.id.tv);
tv.setText(list.get(i));
this.addView(view);
}
}
}
3、使用
<com.ay30.flowlayout.FlowLayout
android:layout_height="wrap_content"
android:id="@+id/flowLayout"
android:layout_width="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp" />
测试数据
FlowLayout flowLayout=findViewById(R.id.flowLayout);
List<String> qualiNameList = new ArrayList<>();
qualiNameList.add("身份证");
qualiNameList.add("道路运输证");
qualiNameList.add("行驶证");
qualiNameList.add("驾驶证");
qualiNameList.add("从业资格证");
qualiNameList.add("押运员证");
qualiNameList.add("安全员证");
qualiNameList.add("营业执照");
qualiNameList.add("道路运输许可证");
qualiNameList.add("道路运输许可证(车挂)");
qualiNameList.add("行驶证(车挂)");
qualiNameList.add("罐检合格证");
flowLayout.initData(qualiNameList);
四、心得
1、想清楚了还是简单,一开始一直不对,后面就先按一个一个搞,像给一面墙贴瓷砖一样。以后遇到这种类似的问题就可以套用同样的模型了。
2、get到重点;测量(onMeasure)与布局(onLayout);
3、数据结构和算法很重要,可以锻炼思维,可以快速知道什么问题用什么算法,而且还不需要怀疑或验证是错的,因为大神或大师已经验证过了;这也是学数学、学算法、学数据结构的目的吧。这才是与计算机沟通的思维。
4、看大神写的代码,可以快速知道怎么实现最好;就好比写文章,你首先要有一定的积累,才能出口成章,快速写完一篇好文章。