标签流布局

先上效果图:2种情况:1、显示很多行,一屏放不下;2、显示指定行数(以2行为例)
1、
第一种情况

2、
第二种情况

以第一种情况讲解,如果用到第二种情况,参见FlowLayout文件中的TODO标记上的讲解。如果一行已经放进来3个数据了,第4要放进来,就超出屏幕宽度,不放进来,就有留白。这时候,处理方法是:不把第4个数据放进来。把留白平分3份,给之前的每个数据加一点宽度,这样好看。
注:这里用了随机生成颜色,每次重新加载,看到的颜色都不一样

实现步骤:
1、将创建FlowLayout文件,将下面源码复制进去

package com.chen.demo;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;

/*
 * 整体思路: 自定义FlowLayout: 1.根据list的size往里面动态添加TextView 2.定义变量:
 * a.horizontalSpacing:子view间的水平间距 b.verticalSpacing: line间的垂直间距
 * c.lineList:用于存放每个line 3.定义Line类:用来记录当前行中的子view,并且提供width和height;
 * width:表示所有子view的宽加上中间的空隙值,在每次添加子view的时候都会更新 height:始终等于当前行中最高子view的高度
 * 4.遍历所有子view过程并判断如下: a.先测量当前childView,保证能获取到宽度和高度
 * b.如果当前line中还没子view,则直接放入,不用判断长度
 * c.当前line中已经有子view的情况:如果line的宽度+horizontalSpacing+child.getMeasuredWidth
 * 大于当前总宽度则立即存储当前line,然后重新new Line(),并将子view加入到new的Line中;
 * 如果不大于总宽度,则将当前childView放入line中;
 * d.注意:每次往line中放子view的时候都需要判断当前子view是否是最后一个;如果是最后一个子 view了,那么久需要将当前line存储,
 * 
 * 5.依次摆放lineList中每个line中保存的子view: a.遍历lineList,取出当前line;
 * b.遍历当前line,取出当前childView;
 * c.如果line是第一行:对childView进行摆放如下:如果childView是第一个,则left是getPaddingLeft,
 * top是getPaddingTop;right是left+自身的宽,bottom是top+自身的高;
 * 如果childView不是第一个,则取出前一个子view(记录为lastChild);则当前childView的left是
 * lastChild的right+horizontalSpacing;top和lastChild一样,right是自身的left+自身的宽;
 * bottom是和lastChild一样;
 * d.如果当前line是第二行,则子view摆放的top需要在getPaddingTop的基础上+line的高度+verticalSpacing;
 * e.最后,由于每行的子view摆放出来之后会有剩余的空间,所以获取剩余的空间,然后除以
 * 子view的数量,得到每个子view应该重新分配的值,对他们的宽重新赋值,并且这个赋值的 操作是在摆放子view之前,因为摆放的时候用到了他们的宽度
 */
public class FlowLayout extends ViewGroup {
   
    /**
     * 默认的间距
     */
    private int DEFAULT_SPACING = 25;
    /**
     * 子view水平方向的间距
     */
    private int horizontalSpacing = 40;
    /**
     * 每行之间的垂直间距
     */
    private int verticalSpacing = 60;
    /**
     * 用来保存每一行line
     */
    private ArrayList<Line> lineList = new ArrayList<Line>();

    /**
     * 有多少行
     */
    int lineNumber = 0;

    public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public FlowLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

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

    /**
     * 分行和测量FlowLayout的宽高
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        lineList.clear();// 开始分行前先清空之前的list

        int width = MeasureSpec.getSize(widthMeasureSpec);// 获得控件的宽度,是包含paddingLeft和paddingRight
        // 这个宽才是我们需要比较用的宽
        int noPaddingWidth = width - getPaddingLeft() - getPaddingRight();// 获取除去padding后的width
        int height = MeasureSpec.getSize(0);// 获取控件的高度

        Line line = null;// 声明为局部变量

        for (
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值