一、代码实现
1. 自动换行控件:AutoLinefeedView.java
package com.stackdump.autolinefeed.widget; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.stackdump.autolinefeed.R; /** * * @author stackdump * @date 2018-07-03 */ public class AutoLinefeedView extends ViewGroup { private static String TAG = "AutoLinefeedView"; private final static int VIEW_MARGIN = 0; public AutoLinefeedView(Context context) { super(context); } public AutoLinefeedView(Context context, AttributeSet attrs) { super(context, attrs); } public AutoLinefeedView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public View addView(final String text) { View pathView = LayoutInflater.from(getContext()).inflate(R.layout.item_path, null); TextView tv = (TextView) pathView.findViewById(R.id.path); tv.setText(text); tv.setPadding(15, 0, 35, 0); addView(pathView); return tv; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //将所有的子View进行测量,这会触发每个子View的onMeasure函数 //注意要与measureChild区分,measureChild是对单个view进行测量 measureChildren(widthMeasureSpec, heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int childCount = getChildCount(); if (childCount == 0) {//如果没有子View,当前ViewGroup没有存在的意义,不用占用空间 setMeasuredDimension(0, 0); } else { //如果宽高都是包裹内容 if (heightMode == MeasureSpec.AT_MOST) {//如果只有高度是包裹内容 //宽度设置为ViewGroup自己的测量宽度,高度设置为所有子View的高度总和 setMeasuredDimension(widthSize, getTotleHeight()); } } } @Override protected void onLayout(boolean arg0, int left, int top, int right, int bottom) { //add by stackdump final int count = getChildCount(); int row = 0;// which row lay you view relative to parent int lengthX = left; // right position of child relative to parent int lengthY = top; // bottom position of child relative to parent for (int i = 0; i < count; i++) { final View child = this.getChildAt(i); int width = child.getMeasuredWidth(); int height = child.getMeasuredHeight(); lengthX += width + VIEW_MARGIN; lengthY = row * (height + VIEW_MARGIN) + VIEW_MARGIN + height + top; // if it can't drawing on a same line , skip to next line if (lengthX > right) { lengthX = width + VIEW_MARGIN + left; row++; lengthY = row * (height + VIEW_MARGIN) + VIEW_MARGIN + height + top; } child.layout(lengthX - width, lengthY - height, lengthX, lengthY); } } //根据子控件个数计算父布局的高度 private int getTotleHeight() { //add by stackdump final int count = getChildCount(); int row = 0;// which row lay you view relative to parent int left = getLeft(); int lengthX = left; // right position of child relative to parent int top = getTop(); int lengthY = top; // bottom position of child relative to parent int right = getMeasuredWidth(); for (int i = 0; i < count; i++) { final View child = this.getChildAt(i); int width = child.getMeasuredWidth(); int height = child.getMeasuredHeight(); lengthX += width + VIEW_MARGIN; lengthY = row * (height + VIEW_MARGIN) + VIEW_MARGIN + height + top; // if it can't drawing on a same line , skip to next line if (lengthX > right) { lengthX = width + VIEW_MARGIN + left; row++; lengthY = row * (height + VIEW_MARGIN) + VIEW_MARGIN + height + top; } } return lengthY; } }
2. 控件调用:MainActivity.java
package com.stackdump.autolinefeed; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.LinearLayout; import com.stackdump.autolinefeed.widget.AutoLinefeedView; public class MainActivity extends AppCompatActivity { private LinearLayout mLayoutPath; private AutoLinefeedView mAutoLinefeedView; private Button mAddBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mAddBtn = (Button)findViewById(R.id.add_btn); //导航 mLayoutPath = (LinearLayout) findViewById(R.id.layout_path); mAutoLinefeedView = new AutoLinefeedView(this); mLayoutPath.addView(mAutoLinefeedView); mAddBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String departmentName = "department"; View tv = mAutoLinefeedView.addView(departmentName); } }); } }
3. 布局文件:activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <!--显示目录层级--> <LinearLayout android:id="@+id/layout_path" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginBottom="20dp" android:background="#bfbfbf"> </LinearLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:layout_below="@+id/layout_path" android:background="#bfbfbf"> <Button android:id="@+id/add_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:gravity="center" android:text="Add" android:textSize="30sp" android:background="@drawable/select_first_button_bg"/> </RelativeLayout> </RelativeLayout>
二、效果图
1.初始界面只有一个Button,每点击一下button,新增一个子控件

2.最终效果图

0