Unity NGUI实现图文混排

为什么要自己写图文混排?

 NGUI的UIlabel本身支持图文混排,只不过只支持位图字体,局限性很强,所以在具体项目中很难满足需求。

自己写的话,有什么想法?

图文混排的基础功能无非:图片或纹理和文字的混合排列,点击行为、超链接、动态支持字号,字色,描边等功能。

之前倒是接触过前辈们写的自定义插件,虽说基本够用但也存在各种问题,结构复杂,排序算法纯属逻辑堆积,维护复杂。

结构设计?

基本思路:使用stringTag解析数据结构,生成数据队列。

使用OO:图文混排中的任何文本,图像,抽象为单个Unit对象,定义一个基础Unit类,包含组件类型,内容记录等属性,其他组件继承基础组件,并在子类中自定义自己的个性方法,不同子类在构造函数中根据传入数据,解析自身属性。并且摒弃逻辑堆叠的排序算法,子类根据传入数据自己处理组件实现自己的排序算法,除此之外,实现点击行为,组件设置等定制行为。

其他需求:行对其方式(上部对其,中间对其,下部对其),RichUnit工厂,根据外部数据构造源串数据,边缘裁切算法。

基类及其子类:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum ContentType
{
	none = 0,			//无
	test = 1,			//纯文本
	testCanClick = 2,	//纯文本可点击
	icon = 3,			//图片
	iconCanClick = 4,	//图片可点击
	texture = 5,		//纹理
	textureCanClick = 6,//纹理可点击
	newLine = 7,		//换行
}

public class RichContentUnit {
	//Unit类型
	public ContentType type;

	//传入的源文本
	public string sourceContent;

	//回传数据
	public string messageContent;

	public bool init = false;

	//父管理组件
	public NGUIRichContentLabel parent;

	//根据当前行高-调整元素位置
	public void AdjustAllLine(List<UIWidget> currentLine, int maxHeight, float standardY)
	{
		float newPos = 0f;
		for (int i = 0; i < currentLine.Count; i++)
		{
			if (currentLine [i].height < maxHeight)
			{
				Vector3 widgetPos = currentLine [i].transform.localPosition;
				newPos = standardY + currentLine [i].height / 2f - maxHeight / 2f;
				if (Mathf.Abs (newPos - widgetPos.y) > 0.001f)//判定为位置需要调整
				{
					currentLine [i].transform.localPosition = new Vector3(widgetPos.x,newPos,0);
				}
			}
		}
	}
}

public class RichLabel : RichContentUnit
{
	public int FontSize;
	public string fontColor;
	public string OutLineColor;
	public string content;
	public List<UILabel> labels;

	public RichLabel(ContentType unitType,string content,NGUIRichContentLabel instance)
	{	
		type = unitType;
		content = content.Replace ("\n",string.Empty);

		//文本@字号@字体颜色@描边颜色@message(点击时回传)
		string[] splitStr = content.Split (NGUIRichContentLabel.splitSign);
		if (splitStr != null && splitStr.Length > 1)
		{
			this.content = splitStr [0];
			init = ParseFontSet (splitStr,instance);
			sourceContent = content;
			parent = instance;
			labels = new List<UILabel> ();
		}
		if (init)
			labels.Add(AddComponent (this.content));
	}

	UILabel AddComponent(string contentSingle,int width = 0, int height = 0)
	{
		GameObject o = new GameObject();
		o.name = "Lable";
		o.layer = parent.gameObject.layer;
		o.transform.parent = parent.gameObject.transform;
		o.transform.localScale = Vector3.one;
		o.transform.localPosition = Vector3.zero;

		UILabel label = o.AddComponent<UILabel>() as UILabel;
		label.trueTypeFont = parent.currentFont;
		label.color = NGUIText.ParseColor(fontColor, 0);
		label.fontSize = FontSize;
		label.keepCrispWhenShrunk = UILabel.Crispness.Never;
		label.useFloatSpacing = true;
		label.floatSpacingX = parent.spaceX;
		if (!string.IsNullOrEmpty(OutLineColor))
		{
			label.effectStyle = UILabel.Effect.Outline;
			label.effectColor = NGUITools.ParseColor (OutLineColor,0);
			label.effectDistance = new Vector2 (0,0);
		}
		else
			label.effectStyle = UILabel.Effect.None;

		label.depth = 0;
		label.pivot = UIWidget.Pivot.TopLeft;
		label.alignment = NGUIText.Alignment.Left;
		label.overflowMethod = UILabel.Overflow.ResizeFreely;
		label.text = contentSingle;

		if (type == ContentType.testCanClick)
		{
			BoxCollider colider = o.AddComponent<BoxCollider> ();
			Vector3 colidersize = new Vector3 (label.width,label.fontSize,0);
			colider.size = colidersize;
			colider.center = new Vector3 (label.width / 2, -label.fontSize / 2,0);
			UIEventListener.Get (label.gameObject).onClick = ClickThisLabel;
		}

		return label;
	}

	public void ResetPosition(ref Vector2 pos,ref int maxHeightofthisLine,ref List<UIWidget> currentLine)
	{
		//超越右边界
		if (pos.x + labels [0].width > parent.Width)
		{
			string allContent = content;

			//需要将当前文本分割成若干段
			int widthNeed = labels [0].width - (parent.Width - (int)pos.x);
			string cutOut = parent.subStringBylength (labels[0],allContent,parent.Width - pos.x);

			//---------------------------------加入残余的半行或整行-----------------------------------
			if (!string.IsNullOrEmpty(cutOut))
			{
				labels [0].text = cutOut;
				labels [0].transfo
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值