之前在UE4项目中遇到需要截断字符用…代替后续字符,这里给出一种方法。
背景
项目需要引入平台昵称,所以出现用户名+平台名超过文本框的长度的情况,如果超过就需要加上省略号。
让策划和美术去根据字体的类型计算字体的长度会增加项目组的工作量。
所以就写了这样一个可以根据指定长度来给字体带上省略号的工具。
function HandleTextBlockCut(widget, cutLength)
local textLength = 0
local text = ""
if widget and cutLength then
widget:ForceLayoutPrepass()
text = widget:GetText()
textLength = widget:GetDesiredSize().X
widget:SetVisibility(UE4.ESlateVisibility.Hidden)
else
return nil
end
if textLength == 0 then
widget:SetVisibility(UE4.ESlateVisibility.Visible)
return nil
end
-- 二分法截取字体合适长度
local shouldCut = cutLength < textLength
if shouldCut then
local tempText = text
local low = 1
local high = #text
local mid = 0
while low < high do
mid = math.ceil((low + high) / 2)
-- 获取字符渲染长度
tempText = TxtUtil.SubUTF8String(tempText, mid).."..."
widget:SetText(tempText)
widget:ForceLayoutPrepass()
textLength = widget:GetDesiredSize().X
if textLength > cutLength then
high = mid - 1
else
low = mid
end
tempText = text
end
text = TxtUtil.SubUTF8String(text,low).."..."
widget:SetText(text)
end
widget:SetVisibility(UE4.ESlateVisibility.Visible)
return widget:GetText()
end
--- sub的改进,截取下标1开始到下标n之间的字符串,并且防止乱码
function SubUTF8String(s, n)
local dropping = string.byte(s, n+1)
if not dropping then return s end
if dropping >= 128 and dropping < 192 then
return TxtUtil.SubUTF8String(s, n-1)
end
return string.sub(s, 1, n)
end
知识点
widget:GetDesiredSize()
可以返回UMG保留的所需长度信息,但是如果没有进行tick的话就是保留上一帧的长度信息。就是永远会是点击上一次的状态。
widget:ForceLayoutPrepass()
Forces a pre-pass. A pre-pass caches the desired size of the widget hierarchy owned by this widget.
可以强制预渲染,计算出UMG长度信息,配合GetDesiredSize就可以做到每次得到临时的大小UE4文档
SubUTF8String(s, n)
如果是一个完整的字符,Byte首位一定是[128,192),利用这点从后往前截断即可