下列均以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)