Unity 根据文本宽度自动裁剪多余文本加后缀"...",包含富文本处理

image.png

下列均以Lua代码编写实现

主要思路:

  • 根据高度判断是否需要裁剪多余行内容
  • 存储富文本
  • 移除富文本
  • 切割多余文本
  • 恢复富文本

根据高度判断是否需要裁剪多余行内容

txt:Unity - Text组件(UnityEngine.UI.Text)
height:计算当前内容占用总高度
one_height:一行内容的高度

    local generator = CS.UnityEngine.TextGenerator()
    local settings = txt:GetGenerationSettings(size)
    local height = generator:GetPreferredHeight(content, settings)
    local one_height = generator:GetPreferredHeight(" ", settings)

存储富文本

local matchs = {}  -- 存储富文本匹配内容
local last_start = 0
for str in string.gmatch(content, "<[^>]->") do
    local start_idx, end_idx = string.find(content, str, last_start)
    last_start = start_idx
    table.insert(matchs, {str = str, start_idx = start_idx, end_idx = end_idx})
end

移除富文本

-- 根据存储的matchs匹配移除
for i, v in ipairs(matchs) do
    content = string.gsub(content, v.match_str or v.str, "")
end

切割多余文本

-- 判断字符对应byte长度
function UTF8LenWord(char)
    if not char then
        return 0
    elseif char > 240 then
        return 4
    elseif char > 225 then
        return 3
    elseif char > 192 then
        return 2
    end
    return 1
end
local len = string.len(content)
local char_lens = {}    -- 记录每个文字的byte长度,后面一个一个切割掉
local idx = 1
while(idx <= len) do
    local c = UTF8LenWord(string.byte(content, idx, idx + 1))
    table.insert(char_lens, 1, c)
    idx = idx + c
end
-- 行数大于1行的根据长度记录进行剔除
while(height/one_height > 1) do
    local sub_count = table.remove(char_lens, 1)
    len = len - sub_count
    content = string.sub(content, 0, len)
    height = generator:GetPreferredHeight(content, settings)
end
-- 最后剔除掉3+个byte
local sub_count = 0
while(sub_count < 3) do
    sub_count = sub_count + table.remove(char_lens, 1)
end
content = string.sub(content, 0, len - sub_count) .. "..."

恢复富文本

-- 最后根据富文本记录恢复富文本
for i, v in ipairs(matchs) do
    local len = string.len(content)
    local start_idx = v.start_idx - 1
    if start_idx > len then
        -- 一般富文本带'/'的作为结尾,匹配不到'/'的且已经超过文本长度时,就不继续执行了
        if not string.match(v.str, "/") then
            break
        end
        start_idx = len
    end
    local left = string.sub(content, 1, start_idx)
    local right = string.sub(content, start_idx + 1, len)
    content = left .. v.str .. right
end

print(content)
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容