- UILabel
1.1 概述
UILabel是NGUI中用于文字显示的组件,支持图文显示,富文本等功能。阅读本文前请熟悉下NGUI的基本用法和基本属性。
1.2 基本用法
1.3 基础属性
溢出类型
效果类型
字体类型
对齐方式
图文样式
渐变
边距
支持富文本
多行和最高行数
1.4 基本原理
- 字体方案有两种:Unity的动态字体(trueTypeFont,TTF)和NGUI的BitmapFont(BMFont)
- UILabel维护mShouldBeProcessed的bool变量,在设置基本属性的时候都会将mShouldBeProcessed设置为true,并重写父类UIWidget的属性drawingDimensions、localCorners、worldCorners、localSize和方法GetSides中判断shouldBeProcessed是否为true,为true则调用UILabel的ProcessText重新计算信息并重新绘制。
- NGUIText作为辅助类,是一个静态类,由于绘制文字的参数很多,由其参数缓存和相应的计算方法,减少相应的内存占用。
- UILabel核心方法
2.1 ProcessText
2.1.1 流程
- 计算UILabel设定的矩形大小和真正显示的矩形大小,其设定矩形大小还受OverFlow类型的影响,如类型为Overflow.ResizeFreely或者Overflow.ResizeHeight相应的设定大小不受当前width height的限制。
- 调用
NGUIText.Update(false)
:更新最终字形的大小、字符间隔finalSpacingX
、 一行高度finalLineHeight
和是否用符文等信息。 - 启用for循环不断递减字体大小
- 调用
NGUIText.WrapText(mText, out mProcessedText, true);
:- 根据regionHeight、finalLineHeight和maxLines计算出Label最多显示的行数;不断遍历字符,解析BBCode跳过用于富文本设置的字符,区分普通字符和图文字符分别计算其字形大小glyphWidth,维护每一行剩余的宽度remainingWidth,当宽度不足的时候就换行,最后返回Label是否容纳全部文本,并得到最终显示的文本finalText。
- 调用
- 调用NGUIText.CalculatePrintedSize(mProcessedText):
- 根据显示的文本mProcessedText和字符间隔
finalSpacingX
、 一行高度finalLineHeight
得到显示rect大小
- 根据显示的文本mProcessedText和字符间隔
- 根据不同OverFlow类型计算Label的宽度和高度。
2.1.2 OverFlow的处理方式
- ShrinkContent:缩放内容;不断递减mPrintedSize调用
NGUIText.WrapText(mText, out mProcessedText, true);
判断目前字体大小是否能显示全部文字,直至满足条件或者字体大小不能再减小。 - ClampContent:裁切内容;调用调用
NGUIText.WrapText(mText, out mProcessedText, true);
得到最终显示的文字。 - ResizeFreely:自适应宽高;调用调用
NGUIText.WrapText(mText, out mProcessedText, true);
得到最终显示的文字。并调用NGUIText.CalculatePrintedSize(mProcessedText);
得到显示的大小,重新计算widget的宽高 - ResizeHeight:自适应高度;类似ResizeFreely,只是重新计算widget的高度。
2.1.3 代码
void ProcessText (bool legacyMode, bool full)
{
if (!isValid) return;
mChanged = true;
shouldBeProcessed = false;
float regionX = mDrawRegion.z - mDrawRegion.x;
float regionY = mDrawRegion.w - mDrawRegion.y;
NGUIText.rectWidth = legacyMode ? (mMaxLineWidth != 0 ? mMaxLineWidth : 1000000) : width;
NGUIText.rectHeight = legacyMode ? (mMaxLineHeight != 0 ? mMaxLineHeight : 1000000) : height;
NGUIText.regionWidth = (regionX != 1f) ? Mathf.RoundToInt(NGUIText.rectWidth * regionX) : NGUIText.rectWidth;
NGUIText.regionHeight = (regionY != 1f) ? Mathf.RoundToInt(NGUIText.rectHeight * regionY) : NGUIText.rectHeight;
mPrintedSize = Mathf.Abs(legacyMode ? Mathf.RoundToInt(cachedTransform.localScale.x) : defaultFontSize);
mScale = 1f;
if (NGUIText.regionWidth < 1 || NGUIText.regionHeight < 0)
{
mProcessedText = "";
return;
}
#if DYNAMIC_FONT
bool isDynamic = (trueTypeFont != null);
if (isDynamic && keepCrisp)
{
UIRoot rt = root;
if (rt != null) mDensity = (rt != null) ? rt.pixelSizeAdjustment : 1f;
}
else mDensity = 1f;
#endif
if (full) UpdateNGUIText();
if (mOverflow == Overflow.ResizeFreely)
{
NGUIText.rectWidth = 1000000;
NGUIText.regionWidth = 1000000;
}
if (mOverflow == Overflow.ResizeFreely || mOverflow == Overflow.ResizeHeight)
{
NGUIText.rectHeight = 1000000;
NGUIText.regionHeight = 1000000;
}
if (mPrintedSize > 0)
{
#if DYNAMIC_FONT
bool adjustSize = keepCrisp;
#endif
for (int ps = mPrintedSize; ps > 0; --ps)
{
#if DYNAMIC_FONT
// Adjust either the size, or the scale
if (adjustSize)
{
mPrintedSize = ps;
NGUIText.fontSize = mPrintedSize;
}
else
#endif
{
mScale = (float)ps / mPrintedSize;
#if DYNAMIC_FONT
NGUIText.fontScale = isDynamic ? mScale : ((float)mFontSize / mFont.defaultSize) * mScale;
#else
NGUIText.fontScale = ((float)mFontSize / mFont.defaultSize) * mScale;
#endif
}
NGUIText.Update(false);
// Wrap the text
bool fits = NGUIText.WrapText(mText, out mProcessedText, true);
if (mOverflow == Overflow.ShrinkContent && !fits)
{
if (--ps > 1) continue;
else break;