UIRichLabel
2016-03-30 20:20
429 查看
using UnityEngine; using System.Collections; using System.Collections.Generic; using System.Text.RegularExpressions; using System; /* * sprite标签格式: <&spritename@height,width&> * framesprite标签格式: <%namepre@defautspritename%> * button标签格式: <!buttontext@eventid@eventcontent!> */ public class UIRichLabel : MonoBehaviour { public UILabel _Target; // 普通图片的格式 const string _SpriteRegex = @"<&[\w@\,]{1,}&>"; const string _Space = @" "; // 帧动画的格式 const string _FrameSpriteRegex = @"<%[\w@]{1,}%>"; const string _FrameSpace = @" "; string _Regex; // button const string _ButtonRegex = @"<![\w@]{1,}!>"; const string _ButtonSprite = "friend_xiangxi"; const string _ButtonSpace = @" "; MatchCollection _Sprites; MatchCollection _FrameSprites; MatchCollection _Buttons; // 分割出来的纯文本信息 List<string> _LableText = new List<string>(); // 字符位置索引,汉字也算一个字符 List<int> _IndicesOffset = new List<int>(); // 所有的富文本信息 List<RichInfo> _RichInfo = new List<RichInfo>(); // 缓存的普通图片节点 List<UISprite> _SpriteNode = new List<UISprite>(); // 缓存的sprite animation节点 List<UISpriteAnimation> _FrameNode = new List<UISpriteAnimation>(); // 缓存的button节点 List<UIButton> _ButtonNode = new List<UIButton>(); [SerializeField] UIFont _UIFont; [SerializeField] Font _TTFFont; public enum RichType { Sprite = 1, FrameSprite = 2, Button = 3, } class RichInfo : IComparable<RichInfo> { public Match _Match; public RichType _Type; public RichInfo(Match match, RichType type) { _Match = match; _Type = type; } public int CompareTo(RichInfo obj) { if(this._Match.Index > obj._Match.Index) { return -1; } else { return 1; } } } void Awake() { _Regex = _SpriteRegex; _Regex += "|" + _FrameSpriteRegex; _Regex += "|" + _ButtonRegex; if(_Target == null) { GameObject go = new GameObject("label"); go.transform.parent = gameObject.transform; go.layer = LayerMask.NameToLayer("UI"); _Target = go.AddComponent<UILabel>(); } //_Target.spacingY = 5; } public void SetSpacing(int x, int y) { if(_Target != null) { _Target.spacingX = x; _Target.spacingY = y; } } public string text { set { if (_Regex == null) { Awake(); } if(_Target == null) { return; } // 校准边缘,避免最后的位置放不满半个fontsize,会有换行问题 _Target.width = (_Target.width/_Target.fontSize)*_Target.fontSize; Reset(); // 把实际的文本内容抽离出来 _LableText.Clear(); //_CurOffset.Clear(); _IndicesOffset.Clear(); _Target.text = string.Empty; _Target.transform.localPosition = Vector3.zero; _LableText = new List<string>(Regex.Split(value, _Regex)); int charCountLine = Mathf.RoundToInt(_Target.width*2/(float)(_Target.fontSize)); //_LableText.RemoveAll(RemoveEmpty); _Sprites = Regex.Matches(value, _SpriteRegex); _FrameSprites = Regex.Matches(value, _FrameSpriteRegex); _Buttons = Regex.Matches(value, _ButtonRegex); BuildRichInfo(); if(_LableText.Count > 1) { for (int i = 0; i < _LableText.Count; i++) { //Debuger.Log(_Target.CalculateOffsetToFit(_LableText[i])); int leftCount = charCountLine - GetStringLen(_Target.text) % charCountLine; if(string.IsNullOrEmpty(_LableText[i])) { if(i == _LableText.Count - 1) { //_CurOffset.Add(GetStringLen(_Target.text)); _IndicesOffset.Add(_Target.text.Length); continue; } //_CurOffset.Add(GetStringLen(_Target.text)); _IndicesOffset.Add(_Target.text.Length); if(i < _RichInfo.Count && _RichInfo[i]._Type == RichType.Button) { if(leftCount >= _ButtonSpace.Length) { _Target.text += _ButtonSpace; } else { for (int ii = 0; ii < leftCount; ii++) { _Target.text += " "; } } } else if(i < _RichInfo.Count && _RichInfo[i]._Type == RichType.FrameSprite) { if(leftCount >= _FrameSpace.Length) { _Target.text += _FrameSpace; } else { for (int ii = 0; ii < leftCount; ii++) { _Target.text += " "; } } } else { if(leftCount >= 2) { _Target.text += _Space; } else { for (int ii = 0; ii < leftCount; ii++) { _Target.text += " "; } } } continue; } _Target.UpdateNGUIText(); _Target.text += _LableText[i]; //_CurOffset.Add(GetStringLen(_Target.text)); _IndicesOffset.Add(_Target.text.Length); leftCount = charCountLine - _Target.text.Length % charCountLine; if(i < _RichInfo.Count && _RichInfo[i]._Type == RichType.Button) { if(leftCount >= _ButtonSpace.Length) { _Target.text += _ButtonSpace; } else { for (int ii = 0; ii < leftCount; ii++) { _Target.text += " "; } } } else if(i < _RichInfo.Count && _RichInfo[i]._Type == RichType.FrameSprite) { if(leftCount >= _FrameSpace.Length) { _Target.text += _FrameSpace; } else { for (int ii = 0; ii < leftCount; ii++) { _Target.text += " "; } } } else { if(i != _LableText.Count - 1) { if(leftCount >= 2) { _Target.text += _Space; } else { for (int ii = 0; ii < leftCount; ii++) { _Target.text += " "; } } } } } } else { _Target.text = value; } // 根据文本,取出里面的字符索引信息和顶点信息,再根据顶点信息去计算富文本的偏移 _Target.UpdateNGUIText(); BetterList<Vector3> verts = new BetterList<Vector3>(); BetterList<int> indices = new BetterList<int>(); NGUIText.PrintApproximateCharacterPositions(_Target.text, verts, indices); // 处理sprite for (int i = 0; i < _Sprites.Count; i++) { int index = GetRichInfoListIndex(_Sprites[i]); if(index == -1) { continue; } // if(index >= _CurOffset.Count) // { // return; // } //int startIndex = _CurOffset[index]; // 计算在第几行 //int localLine = (int)(startIndex/charCountLine) + 1; // 计算在当前的第几个字节 //int curLinePos = startIndex - charCountLine*(localLine-1); // 计算横向偏移 //int offsetX = Mathf.RoundToInt((curLinePos+1)*_Target.fontSize/2); Vector3 pos = verts[_IndicesOffset[index]*2]; float offsetX = pos.x + _Target.fontSize/2; //Debuger.LogError(curLinePos + "==" + verts[_IndicesOffset[index]*2]); // 计算纵向偏移 //int offsetY = _Target.fontSize/2 + Mathf.RoundToInt((localLine-1)*_Target.fontSize); float offsetY = pos.y; string info = GetSpriteName(_Sprites[i].Value); if(info != null) { string[] splits = info.Split('@'); string spriteName = splits[0]; int height = _Target.fontSize; int width = _Target.fontSize; if(splits.Length > 1) { string[] spriteInfo = splits[1].Split(','); if(spriteInfo.Length > 1) { int tmpHeight = 0; int tmpWidth = 0; if(int.TryParse(spriteInfo[0], out tmpHeight)) { height = tmpHeight; } if(int.TryParse(spriteInfo[1], out tmpWidth)) { width = tmpWidth; } } } UISprite node = AddSpriteNode(); node.depth = _Target.depth + 1; node.width = width; node.height = height; node.transform.localPosition = _Target.transform.localPosition + new Vector3(offsetX, offsetY, 0); //Debuger.LogError(_Target.transform.localPosition + "--" + offsetX); NGUIAtlasManager.GetInstance().Attach(node, spriteName); node.gameObject.SetActive(true); } } for (int i = 0; i < _FrameSprites.Count; i++) { int index = GetRichInfoListIndex(_FrameSprites[i]); if(index == -1) { continue; } Vector3 pos = verts[_IndicesOffset[index]*2]; float offsetX = pos.x + _Target.fontSize/2; float offsetY = pos.y; string info = GetFrameSpriteNamePre(_FrameSprites[i].Value); if(info != null) { string[] splits = info.Split('@'); UISpriteAnimation node = null; if(splits.Length >= 2) { node = AddFrameSprite(splits[0], splits[1]); } else { continue; } node.transform.localPosition = _Target.transform.localPosition + new Vector3(offsetX + 9, offsetY, 0); node.gameObject.SetActive(true); } } for (int i = 0; i < _Buttons.Count; i++) { int index = GetRichInfoListIndex(_Buttons[i]); if(index == -1) { continue; } Vector3 pos = verts[_IndicesOffset[index]*2]; float offsetX = pos.x + _Target.fontSize/2; float offsetY = pos.y; string info = GetButtonName(_Buttons[i].Value); if(info != null) { string[] splits = info.Split('@'); UIButton node = null; if(splits.Length > 2) { node = AddButtonNode(splits[0]); node.onClick.Clear(); EventDelegate del = new EventDelegate(this, "OnButtonClick"); del.parameters[0] = new EventDelegate.Parameter(splits[1]); del.parameters[1] = new EventDelegate.Parameter(splits[2]); node.onClick.Add(del); } else { node = AddButtonNode(info); } node.transform.localPosition = _Target.transform.localPosition + new Vector3(offsetX + 36, offsetY, 0); node.gameObject.SetActive(true); } } //_Target.text = _Target.text.Replace(@"''","[707070]''[-]"); } } UISprite AddSpriteNode() { UISprite cache = GetSpriteNodeFromCache(); if(cache != null) { return cache; } GameObject go = new GameObject("sprite"); go.layer = LayerMask.NameToLayer("UI"); go.transform.parent = gameObject.transform; go.transform.localScale = Vector3.one; UISprite sprite = go.AddComponent<UISprite>(); _SpriteNode.Add(sprite); return sprite; } UISpriteAnimation AddFrameSprite(string namepre, string defaultname) { UISpriteAnimation cache = GetFrameSpriteFromCache(); if(cache != null) { cache.namePrefix = namepre; NGUIAtlasManager.Instance.Attach(cache.Sprite, defaultname); return cache; } GameObject go = new GameObject("framesprite"); go.layer = LayerMask.NameToLayer("UI"); go.transform.parent = gameObject.transform; go.transform.localScale = Vector3.one; UISprite sprite = go.AddComponent<UISprite>(); NGUIAtlasManager.Instance.Attach(sprite, defaultname); sprite.height = _Target.fontSize*2; sprite.width = _Target.fontSize*2; sprite.depth = _Target.depth + 2; cache = go.AddComponent<UISpriteAnimation>(); cache.namePrefix = namepre; cache.Snap = false; cache.framesPerSecond = 10; _FrameNode.Add(cache); return cache; } UIButton AddButtonNode(string text) { UIButton cache = GetButtonNodeFromCache(); if(cache != null) { UILabel lab = cache.GetComponentInChildren<UILabel>(); if(lab != null) { lab.text = text; } return cache; } GameObject go = NGUITools.AddChild(gameObject); go.name = "Button"; UISprite bg = NGUITools.AddWidget<UISprite>(go); bg.type = UISprite.Type.Sliced; bg.name = "Background"; bg.width = 80; bg.height = 35; bg.depth = 15; NGUIAtlasManager.Instance.Attach(bg, _ButtonSprite); UILabel lbl = NGUITools.AddWidget<UILabel>(go); if(_UIFont != null) { lbl.bitmapFont = _UIFont; lbl.trueTypeFont = null; } else { lbl.bitmapFont = null; lbl.trueTypeFont = _TTFFont; } lbl.text = text; lbl.depth = 18; lbl.UpdateNGUIText(); lbl.AssumeNaturalSize(); // Add a collider NGUITools.AddWidgetCollider(go); // Add the scripts cache = go.AddComponent<UIButton>(); cache.tweenTarget = bg.gameObject; cache.pressed = Color.gray; go.AddComponent<UIPlaySound>(); _ButtonNode.Add(cache); return cache; } void Reset() { for (int i = 0; i < _SpriteNode.Count; i++) { if(_SpriteNode[i] != null) _SpriteNode[i].gameObject.SetActive(false); } for (int i = 0; i < _ButtonNode.Count; i++) { if(_ButtonNode[i] != null) _ButtonNode[i].gameObject.SetActive(false); } } UISprite GetSpriteNodeFromCache() { for (int i = 0; i < _SpriteNode.Count; i++) { if(_SpriteNode[i] != null && _SpriteNode[i].gameObject.activeSelf == false) { return _SpriteNode[i]; } } return null; } UISpriteAnimation GetFrameSpriteFromCache() { for (int i = 0; i < _FrameNode.Count; i++) { if(_FrameNode[i] != null && _FrameNode[i].gameObject.activeSelf == false) { return _FrameNode[i]; } } return null; } UIButton GetButtonNodeFromCache() { for (int i = 0; i < _ButtonNode.Count; i++) { if(_ButtonNode[i] != null && _ButtonNode[i].gameObject.activeSelf == false) { return _ButtonNode[i]; } } return null; } /// <summary> /// 根据索引,排序所有富文本信息,要用这个来添加节点 /// </summary> void BuildRichInfo() { _RichInfo.Clear(); for (int i = 0; i < _Sprites.Count; i++) { _RichInfo.Add(new RichInfo(_Sprites[i], RichType.Sprite)); } for (int i = 0; i < _FrameSprites.Count; i++) { _RichInfo.Add(new RichInfo(_FrameSprites[i], RichType.FrameSprite)); } for (int i = 0; i < _Buttons.Count; i++) { _RichInfo.Add(new RichInfo(_Buttons[i], RichType.Button)); } _RichInfo.Sort(); _RichInfo.Reverse(); } /// <summary> /// 获取字符长度,一个汉字算2个 /// </summary> /// <returns>The string length.</returns> /// <param name="str">String.</param> int GetStringLen(string str) { if(string.IsNullOrEmpty(str)) { return 0; } return System.Text.Encoding.UTF8.GetBytes(str).Length; } int GetRichInfoListIndex(Match match) { for (int i = 0; i < _RichInfo.Count; i++) { if(_RichInfo[i]._Match == match) { return i; } } return -1; } /// <summary> /// 解析图片标签,返回spriteName /// </summary> /// <returns>The sprite info.</returns> /// <param name="expression">Expression.</param> string GetSpriteName(string expression) { if(string.IsNullOrEmpty(expression)) { return null; } expression = expression.Replace("<&", ""); expression = expression.Replace("&>", ""); return expression; } string GetButtonName(string expression) { if(string.IsNullOrEmpty(expression)) { return null; } expression = expression.Replace("<!", ""); expression = expression.Replace("!>", ""); return expression; } string GetFrameSpriteNamePre(string expression) { if(string.IsNullOrEmpty(expression)) { return null; } expression = expression.Replace("<%", ""); expression = expression.Replace("%>", ""); return expression; } public int LineCount { get { if(_Target != null) { return _Target.height / _Target.fontSize; } return -1; } } public int FontSize { get { if(_Target != null) { return _Target.fontSize; } else { return 1; } } } void OnButtonClick(string eventId, string info) { int clientEvent = -1; if(int.TryParse(eventId, out clientEvent) == false) { Debug.LogError("eventid is not num!"); return; } if(clientEvent >= (int)NTFrame.GameEvent.GameEventID.GECount) { Debug.LogError("illegal event id!"); return; } ClientEvent eve = new ClientEvent(); eve.AddParameter(info); ClientEventManager.Instance.ActiveEvent((NTFrame.GameEvent.GameEventID)clientEvent, eve); } }
相关文章推荐
- windowbuilder入门
- IOS开发-UI学习-UITextField的各种属性设置
- UIKit层面的动画
- 关于String,StringBuffer与StringBuilder
- dom4j-Quick Start Guide
- UILabel、UITextView自适应得到高度
- ACM程序设计选修课——1043: Radical loves integer sequences(YY)
- 从Long.ValueOf("String")与Long.parseLong("String")看JAVA包装类的封箱与拆箱
- iOS程序的Build过程
- The global shader cache file'X:/XXXX/GlobalShaderCache-PCD3D_SM5.bin' is missing——UE4工程运行失败
- POJ-1679 The Unique MST ( 次小生成树 )
- Long.valueOf()作用
- easyui 获取子节点并修改节点颜色
- IOS学习之——UIEvent 控件的学习
- IOS学习之——UITouch 控件的学习
- IOS学习之——UIResponder
- UIPageViewController用法
- 关于UIView中的坐标转换
- LeetCode之300—-Longest Increasing Subsequence
- 【转】于request.getSession(true/false/null)的区别