NGUI-UILabel源码解析

  1. UILabel
    1.1 概述
    UILabel是NGUI中用于文字显示的组件,支持图文显示,富文本等功能。阅读本文前请熟悉下NGUI的基本用法和基本属性。
    1.2 基本用法
    UILabel1.png

UILabel2.png

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作为辅助类,是一个静态类,由于绘制文字的参数很多,由其参数缓存和相应的计算方法,减少相应的内存占用。
  1. 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大小
  • 根据不同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 mPro
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值