流式布局FlowLayout支持行数控制,单选,多选,点击等操作

本文介绍了如何封装一个自定义的FlowLayout,该布局支持行数控制、单选、多选以及点击操作。通过对外暴露关键参数,如行数限制、是否溢出等,实现动态布局。在测量阶段限制行数,放置位置时避免超出限制,并通过自定义Adapter提供数据源。同时,数据变化时更新ViewGroup和Tag的显示状态,监听标签的点击和选中事件。通过重写dispatchDraw方法来判断流布局是否溢出,并提供使用示例。
摘要由CSDN通过智能技术生成

最近有这么一个需求,如下图

开发中内容搜索页面经常会记录搜索关键字,搜索关键字长度不一,我们通过会采用自定义流布局的方式展示;流布局的基本需要是动态添加childView并实现自动换行操作,这个操作比较简单,重写ViewGroup的onMeasure()方法,遍历动态计算每个View的宽高,宽度累加,当超过ViewGroup宽度时,则换行显示,负责设置子控件的测量模式和大小,根据所有子控件设置自己的宽和高;然后重写onLayout()方法,完成对所有的childView的位置以及大小的指定;

我们有时候也会显示用户标签,标签长度不一,标签不光可以点击,还可以选中多个标签,那么我们是否可以封装一个常见流布局的呢?当然可以,我封装一个支持行数控制,单选,多选,点击等操作的流布局控件;

1.对外暴露关键参数

首先加了几个对外暴露的变量

  • 变量limitLineCount表示默认显示的行数,变量isLimitLine表示是否有行数限制,这个是根据自身去求动态设置的;
  • 另外一个参数isOverFlow是否溢出,因为接口返回的数据数量是不确定的,可能不会超过行限制,也可能超过行限制,如果超过,则显示点击显示全部按钮,所以这个参数是起到这个作用的;
  • 变量mOnTagClickListener和mOnTagSelectListener分别表示标签点击和标签选中事件回调;
  • 变量mTagCheckMode表示标签选中模式,点击,单选,多选;
  • 变量isMoreListener表示是否需要显示更多按钮,即超出要显示的行数;
    /**
     * 流布局不支持被选中
     */
    public static final int FLOW_TAG_CHECKED_NONE = 0;
    /**
     * 流布局支持单选
     */
    public static final int FLOW_TAG_CHECKED_SINGLE = 1;
    /**
     * 流布局支持多选
     */
    public static final int FLOW_TAG_CHECKED_MULTI = 2;

    /**
     * 监听数据集变化
     */
    AdapterDataSetObserver mDataSetObserver;

    /**
     * 含有数据及显示视图的Adapter
     */
    ListAdapter mAdapter;

    /**
     * 标签点击事件回调
     */
    OnTagClickListener mOnTagClickListener;

    /**
     * 标签被选中事件回调
     */
    OnTagSelectListener mOnTagSelectListener;

    /**
     * 是否有行限制
     */
    boolean isLimitLine = true;

    /**
     * 限制显示的行数
     */
    int limitLineCount = 1;

    /**
     * 是否溢出,即超过要求显示行数
     */
    boolean isOverFlow;

    /**
     * 标签流式布局选中模式,默认是不支持选中的
     */
    private int mTagCheckMode = FLOW_TAG_CHECKED_NONE;

    /**
     * 存储选中的tag
     */
    private SparseBooleanArray mCheckedTagArray = new SparseBooleanArray();

    /**
     * 超过限制显示行数函数回调
     */
    private IsMoreListener isMoreListener;

2.测量时做行数限制

如果超过,则不继续测量高度

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 获得它的父容器为它设置的测量模式和大小
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // 获取Padding
        // 获得它的父容器为它设置的测量模式和大小
        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
        int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
        int modeHeight = MeasureSpec.getMode(heightMeasureSpec);

        //FlowLayout最终的宽度和高度值
        int resultWidth = 0;
        int resultHeight = 0;

        //测量时每一行的宽度,width不断取最大宽度
        int lineWidth = 0;
        //测量时每一行的高度,加起来就是FlowLayout的高度
        int lineHeight = 0;
        //流布局的行数
        int currLines = 0;
        //流布局子视图的数量
        int chi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值