具有自动换行功能的LinearLayout

自定义自动换行的LinearLayout

1 MyAutoLineFeedLinearLayout

是用来承载内容的父控件,定义代码如下:

package com.gsww.hzz.uikit.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;

import com.gsww.hzz.uikit.R;

/**
 * @author Qzl
 * @desc 自定义自动换行LinearLayout
 * @email 2538096489@qq.com
 * @time 2019-02-25 16:02
 * @class hzz
 * @package com.gsww.hzz.uikit.view
 */
public class MyAutoLineFeedLinearLayout extends LinearLayout {
    //设置一行显示多少个,默认为三个
    int mAutoLineNum = 3;
    /**
     * 里面内容的行间距 下一行距离上一行的间距
     */
    float mAutoLineTop = 0;
    /**
     * 每一行显示的view的总宽度
     */
    private int childWidth = 0;
    /**
     * 屏幕的最大宽度
     */
    private int maxWidth = 0;

    public MyAutoLineFeedLinearLayout(Context context) {
        super(context);
    }

    public MyAutoLineFeedLinearLayout(Context context, int horizontalSpacing, int verticalSpacing) {
        super(context);
    }

    public MyAutoLineFeedLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        //获取自定义属性的值
        TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.AutoLineFeedLinearLayout);
        mAutoLineNum = arr.getInt(R.styleable.AutoLineFeedLinearLayout_auto_line_num,3);
        mAutoLineTop = arr.getDimension(R.styleable.AutoLineFeedLinearLayout_auto_line_top,0);
        //释放资源
        arr.recycle();
    }

    /**
     * @desc 测量方法,计算显示这些view所需要的高度
     * @author 强周亮
     * @time 2019-02-26 09:48
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //获取屏幕的宽度
        maxWidth = MeasureSpec.getSize(widthMeasureSpec);
        int y = getTotalHeight();
        //设置容器所需的宽高
        setMeasuredDimension(maxWidth, y);
    }

    /**
     * @desc 获取布局总高度
     * @author 强周亮
     * @time 2019-02-26 11:48
     */
    private int getTotalHeight() {
        //每一次测量时,重新计算每行所有view的总宽度,用来做均分显示
        childWidth = 0;
        //获取总共的子view的个数
        int childCount = getChildCount();
        //计算子view所占的宽度
        int x = 0;
        //计算子view所占的高度
        int y = 0;
        //记录总共有多少行
        int row = 0;
        //记录是第几个孩子
        int indexChild = -1;
        for (int index = 0; index < childCount; index++){
            final View child = getChildAt(index);
            if (child.getVisibility() != View.GONE){
                indexChild++;
                child.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
                //此处增加换行判断,用于计算所需的高度
                int width = child.getMeasuredWidth();
                int height = child.getMeasuredHeight();
                x += width;
                if (indexChild < mAutoLineNum) {
                    childWidth += width;
                };
                y = (row+1)*(int)(height+ mAutoLineTop);
                if ((indexChild != 0 && indexChild%mAutoLineNum== 0) || x > maxWidth){
                    x = width;
                    row++;
                    y = (row+1)*(int)(height+ mAutoLineTop);
                }
            }
        }
        return y;
    }

    /**
     * @desc 绘制要显示的view
     * @author 强周亮
     * @time 2019-02-26 09:53
     */
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childCount = getChildCount();
        int x = 0,y,row  = 0,span = 0,maxWidth = r - 1;
        span = getSpan(span, maxWidth);
        childLayout(childCount, x, row, span, maxWidth);
    }

    /**
     * @desc 绘制每一个孩子
     * @author 强周亮
     * @time 2019-02-26 11:50
     */
    private void childLayout(int childCount, int x, int row, int span, int maxWidth) {
        int y;//记录是第几个孩子
        int indexChild = -1;
        for (int i = 0; i < childCount; i++) {
            final View child = this.getChildAt(i);
            if (child.getVisibility() != View.GONE){
                indexChild++;
                int width = child.getMeasuredWidth();
                int height = child.getMeasuredHeight();
                x += width+span;
                y = (int) (row+1)*(int)(height+ mAutoLineTop);
                if ((indexChild != 0 && indexChild%mAutoLineNum== 0) || x > maxWidth){
                    x = width+span;
                    row++;
                    y = (int) (row+1)*(int)(height+ mAutoLineTop);
                }
                child.layout(x - width, y - height, x, y);
            }
        }
    }

    /**
     * @desc 获取每一行之间view的间距
     * @author 强周亮
     * @time 2019-02-26 11:49
     */
    private int getSpan(int span, int maxWidth) {
        if (childWidth < maxWidth){
            span = (maxWidth-childWidth)/(mAutoLineNum+1);
        }
        return span;
    }
}

2 attrs.xml 属性值

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!--自定义linearlayout可以换行显示-->
    <declare-styleable name="AutoLineFeedLinearLayout">
        <!--每一行显示多少个-->
        <attr name="auto_line_num" format="integer"/>
        <!--行与行之间的间距-->
        <attr name="auto_line_top" format="dimension"/>
    </declare-styleable>
</resources>

3 使用

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:orientation="vertical"
    tools:context=".fragment.JobsFragment">
    <com.gsww.hzz.uikit.view.MyAutoLineFeedLinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:auto_line_num = "3"
        app:auto_line_top = "@dimen/dp_26">
        <LinearLayout
            android:id="@+id/one_picture"
            style="@style/job_tv_parent">
            <ImageView
                style="@style/job_img"
                android:src="@drawable/icon_job_one_pic" />
            <TextView
                style="@style/job_tv"
                android:text="@string/one_map"/>
        </LinearLayout>
    </com.gsww.hzz.uikit.view.MyAutoLineFeedLinearLayout>
</LinearLayout>

4 style样式

<!--每一行中每一个的父布局-->
    <style name="job_tv_parent">
        <item name="android:layout_width">0dp</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_weight">1</item>
        <item name="android:gravity">center</item>
        <item name="android:orientation">vertical</item>
    </style>
    <style name="job_img">
        <item name="android:layout_width">@dimen/dp_54</item>
        <item name="android:layout_height">@dimen/dp_54</item>
    </style>
    <!--TextView布局-->
    <style name="job_tv">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:textSize">@dimen/text_size_14</item>
        <item name="android:textColor">#666666</item>
        <item name="android:layout_marginTop">@dimen/dp_8</item>
    </style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值