Android 添加子控件自动换行

一、代码实现

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,新增一个子控件

111

2.最终效果图

222
0

留下评论