UGUI 标签流(流式布局)

目的:

今天要做一个基于UGUI标签流的功能的文档。标签流的作用在于:在日常的App中,时常会涉及到对热门、推荐等标签自动换行的流式布局。常用于关键词搜索或者热门标签等场景

类似于下面:

流式布局的原理:当某一行的空间不足容纳新的内容时,自动向下一行移动

如下:

      

所涉及到的重点:

(1)通过字体及字符串Length,获取字符串所占Text长度(显示的像素)
(2)计算当前行剩余空间是否能容纳下一个标签

代码如下所示:


1:通过字体及字符串长度获取字符串显示长度:

    /// <summary>
    /// 通过字体及字符串长度获取某字符串显示长度(像素)
    /// </summary>
    /// <param name="fontsize">字号</param>
    /// <param name="text">内容</param>
    /// <param name="fontStyle">字体类型(普通、加粗、倾斜)</param>
    /// <param name="path">字体路径</param>
    /// <returns></returns>
    float GetTextWidth(int fontsize,string text,FontStyle fontStyle,string path)
    {
        Font font = Resources.Load<Font>(path);
        font.RequestCharactersInTexture(text, fontsize, fontStyle);
        CharacterInfo characterInfo;
        float width = 0f;
        for (int i = 0; i < text.Length; i++)
        {
            font.GetCharacterInfo(text[i], out characterInfo, fontsize);
            width += characterInfo.advance;
        }
        return width;
    }

2:通过克隆并显示一个Button

/// <summary>
    /// 通过克隆并显示一个Button
    /// </summary>
    /// <param name="ContentText">Button文字</param>
    /// <param name="objParent">初始化后Button的父物体(容纳的Box)</param>
    /// <param name="info">字符串相关信息(字号、字体、类型、路径等)</param>
    /// <returns></returns>
    GameObject GetInitButton(string ContentText,Transform objParent,OriginInfo info)
    {
        var textWidth = GetTextWidth(info._fontsize, ContentText, info._fontStyle, info._fontPath);
        var btn = (GameObject)Object.Instantiate(Resources.Load(info._btnResPath));
        btn.transform.SetParent(objParent);
        btn.GetComponent<RectTransform>().sizeDelta = new Vector2(textWidth + info._addRect.x, info._addRect.y);
        btn.GetComponentInChildren<UnityEngine.UI.Text>().text = ContentText;
        btn.transform.localScale = Vector3.one;
        return btn;
    }


3:标签流显示

/// <summary>
    /// 标签流展示
    /// </summary>
    /// <param name="labelFlowOrignInfo"></param>
    /// <param name="contentList">字符串列表(所要展示的Button流)</param>
    /// <param name="objParent"></param>
    /// <param name="info"></param>
    public  void LabelFlowShow(LabelFlowOrigin labelFlowOrignInfo, List<string> contentList,Transform objParent,OriginInfo info)
    {
        labelFlowOrignInfo._totalLength = labelFlowOrignInfo._paddingLeft;
        var parentWidth = objParent.GetComponent<RectTransform>().sizeDelta.x;//当父物体没有做拉伸时
        for (int i = 0; i < contentList.Count; i++)
        {
            //Initialization button 
            var objButton = GetInitButton(contentList[i], objParent,info);
            var objButtonRect = objButton.GetComponent<RectTransform>();
            //Control button postion
            if (labelFlowOrignInfo._totalLength + objButtonRect.sizeDelta.x + labelFlowOrignInfo._paddingRight > parentWidth)
            {
                labelFlowOrignInfo._totalLength = labelFlowOrignInfo._paddingLeft;
                labelFlowOrignInfo._rows++;
            }
            objButton.GetComponent<RectTransform>().localPosition = new Vector3(labelFlowOrignInfo._totalLength, -labelFlowOrignInfo._spacingVertical * labelFlowOrignInfo._rows - objButtonRect.sizeDelta.y * (labelFlowOrignInfo._rows - 1), 0);
            labelFlowOrignInfo._totalLength += objButtonRect.sizeDelta.x + labelFlowOrignInfo._spacingHorizontal;
        }
    }


4:两个类用于代码管理

/// <summary>
/// 两个类用于代码管理
/// </summary>
public class LabelFlowOrigin
{
    public float _paddingLeft;//左边距
    public float _paddingRight;//右边距
    public float _paddingUp;//上边距
    public float _spacingHorizontal;//行间距
    public float _spacingVertical;//列间距
    public float _totalLength;//某行的当前长度
    public int _rows;//第几行
    public LabelFlowOrigin(float paddingLeft, float paddingRight, float paddingUp, float spacingHorizonta, float spacingVertical, float totalLength, int rows)
    {
        this._paddingLeft = paddingLeft;
        this._paddingRight = paddingRight;
        this._paddingUp = paddingUp;
        this._spacingHorizontal = spacingHorizonta;
        this._spacingVertical = spacingVertical;
        this._totalLength = totalLength;
        this._rows = rows;
    }
}
public  class OriginInfo
{
    public int _fontsize;//字号
    public FontStyle _fontStyle;//类型
    //Button的显示(x——Button背景比字符串本身左右宽多少长度,y——Button高度)
    public Vector2 _addRect;
    public string _fontPath;//字体路径
    public string _btnResPath;//Button预制体路径
    public OriginInfo(int fontsize, FontStyle fontStyle, Vector2 addRect, string fontPath, string btnResPath)
    {
        this._fontPath = fontPath;
        this._fontStyle = fontStyle;
        this._fontsize = fontsize;
        this._addRect = addRect;
        this._btnResPath = btnResPath;
    }
}


全部代码如下所示:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// 标签流——Made By XXQQ
/// </summary>
public class InitLabelFlow
{
    #region    singleton
    static InitLabelFlow instance = null;
    public static InitLabelFlow Instance
    {
        get
        {
            if (instance == null)
                instance = new InitLabelFlow();
            return instance;
        }
    }
    #endregion;
    /// <summary>
    /// 通过字体及字符串长度获取某字符串显示长度(像素)
    /// </summary>
    /// <param name="fontsize">字号</param>
    /// <param name="text">内容</param>
    /// <param name="fontStyle">字体类型(普通、加粗、倾斜)</param>
    /// <param name="path">字体路径</param>
    /// <returns></returns>
    float GetTextWidth(int fontsize,string text,FontStyle fontStyle,string path)
    {
        Font font = Resources.Load<Font>(path);
        font.RequestCharactersInTexture(text, fontsize, fontStyle);
        CharacterInfo characterInfo;
        float width = 0f;
        for (int i = 0; i < text.Length; i++)
        {
            font.GetCharacterInfo(text[i], out characterInfo, fontsize);
            width += characterInfo.advance;
        }
        return width;
    }
    /// <summary>
    /// 通过克隆并显示一个Button
    /// </summary>
    /// <param name="ContentText">Button文字</param>
    /// <param name="objParent">初始化后Button的父物体(容纳的Box)</param>
    /// <param name="info">字符串相关信息(字号、字体、类型、路径等)</param>
    /// <returns></returns>
    GameObject GetInitButton(string ContentText,Transform objParent,OriginInfo info)
    {
        var textWidth = GetTextWidth(info._fontsize, ContentText, info._fontStyle, info._fontPath);
        var btn = (GameObject)Object.Instantiate(Resources.Load(info._btnResPath));
        btn.transform.SetParent(objParent);
        btn.GetComponent<RectTransform>().sizeDelta = new Vector2(textWidth + info._addRect.x, info._addRect.y);
        btn.GetComponentInChildren<UnityEngine.UI.Text>().text = ContentText;
        btn.transform.localScale = Vector3.one;
        return btn;
    }
    /// <summary>
    /// 标签流显示
    /// </summary>
    /// <param name="labelFlowOrignInfo"></param>
    /// <param name="contentList">字符串列表(所要展示的Button流)</param>
    /// <param name="objParent"></param>
    /// <param name="info"></param>
    public  void LabelFlowShow(LabelFlowOrigin labelFlowOrignInfo, List<string> contentList,Transform objParent,OriginInfo info)
    {
        labelFlowOrignInfo._totalLength = labelFlowOrignInfo._paddingLeft;
        var parentWidth = objParent.GetComponent<RectTransform>().sizeDelta.x;//当父物体没有做拉伸时
        for (int i = 0; i < contentList.Count; i++)
        {
            //Initialization button 
            var objButton = GetInitButton(contentList[i], objParent,info);
            var objButtonRect = objButton.GetComponent<RectTransform>();
            //Control button postion
            if (labelFlowOrignInfo._totalLength + objButtonRect.sizeDelta.x + labelFlowOrignInfo._paddingRight > parentWidth)
            {
                labelFlowOrignInfo._totalLength = labelFlowOrignInfo._paddingLeft;
                labelFlowOrignInfo._rows++;
            }
            objButton.GetComponent<RectTransform>().localPosition = new Vector3(labelFlowOrignInfo._totalLength, -labelFlowOrignInfo._spacingVertical * labelFlowOrignInfo._rows - objButtonRect.sizeDelta.y * (labelFlowOrignInfo._rows - 1), 0);
            labelFlowOrignInfo._totalLength += objButtonRect.sizeDelta.x + labelFlowOrignInfo._spacingHorizontal;
        }
    }
}
/// <summary>
/// 两个类用于代码管理
/// </summary>
public class LabelFlowOrigin
{
    public float _paddingLeft;//左边距
    public float _paddingRight;//右边距
    public float _paddingUp;//上边距
    public float _spacingHorizontal;//行间距
    public float _spacingVertical;//列间距
    public float _totalLength;//某行的当前长度
    public int _rows;//第几行
    public LabelFlowOrigin(float paddingLeft, float paddingRight, float paddingUp, float spacingHorizonta, float spacingVertical, float totalLength, int rows)
    {
        this._paddingLeft = paddingLeft;
        this._paddingRight = paddingRight;
        this._paddingUp = paddingUp;
        this._spacingHorizontal = spacingHorizonta;
        this._spacingVertical = spacingVertical;
        this._totalLength = totalLength;
        this._rows = rows;
    }
}
public  class OriginInfo
{
    public int _fontsize;//字号
    public FontStyle _fontStyle;//类型
    //Button的显示(x——Button背景比字符串本身左右宽多少长度,y——Button高度)
    public Vector2 _addRect;
    public string _fontPath;//字体路径
    public string _btnResPath;//Button预制体路径
    public OriginInfo(int fontsize, FontStyle fontStyle, Vector2 addRect, string fontPath, string btnResPath)
    {
        this._fontPath = fontPath;
        this._fontStyle = fontStyle;
        this._fontsize = fontsize;
        this._addRect = addRect;
        this._btnResPath = btnResPath;
    }
}
标签流测试用例
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// 标签流测试用例
/// </summary>
public class Test : MonoBehaviour
{
    void Start()
    {
        var labelFlowOrigin = new LabelFlowOrigin(10, 10, 0, 30, 30, 0, 1);
        List<string> contentList = new List<string>() { "跪下,叫爸爸!", "我是Bruce", "XXQQ", "今天的天气哈哈哈", "落霞与孤鹜齐飞", "Smiles Of Roses","我在马路边捡到一分钱","震惊——" };
        var parent = GameObject.Find("Image").transform;
        var originInfo = new OriginInfo(24, FontStyle.Normal, new Vector2(60, 50), "font/DroidSansFallback", "XQResources/CollectionButton");
        InitLabelFlow.Instance.LabelFlowShow(labelFlowOrigin, contentList, parent, originInfo);
    }
}

实用效果:




  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值