Unity3D NGUI图文混排聊天表情
来源:互联网 发布:电视机的网络接口 编辑:程序博客网 时间:2024/05/14 03:56
原创文章如需转载请注明:转载自 脱莫柔Unity3D学习之旅 Unity3D引擎技术交流QQ群:【119706192】本文链接地址: Unity3D NGUI图文混排的聊天表情
历时1年开发的mmorpg游戏终于进入收尾阶段,最后还差些需要提升表现力的小功能没做。比如图文混排聊天表情。网上找了插件对接半天发现插件各种bug,修复实在困难,焦躁之下最终决定自己写!
最为一个cv战士,生存的原则就是能ctrl+c ctrl+v 实现的功能,坚决不自己写,这么普及的功能,网上肯定有人写。
然后我就找到了蛮牛的师兄弟写的这篇文章http://www.manew.com/blog-3649-2595.html
推算不出来他藏起来的NGUIText.CalculatePrintedSize()功能是做了什么实现,我返回的宽度结果居然是(0,高度),原文展示的代码部分思路我也看不明白。
没办法,还是自己动手吧。于是自己做了一套获取每个字符累加宽度的方式实现了一版。核心代码如下:
void replaceFace(ref string text) { eList.Clear(); float lineW = 0; float low = 0; float fontSize = mLabel.fontSize; for (int i = 0; i < text.Length; i++) { float cWidth = 0; int isface = -1; Debug.Log(text[i]); if (text[i] == '#' && i + 4 < text.Length && text[i + 2] == '_') { cWidth = faceWidth; isface = i; } else { int charW; if (!GetCharWidth(text[i], out charW)) { text = text.Remove(isface, faceNamelength); text = text.Insert(isface, spaceChar.ToString()); } cWidth += charW; } StringBuilder spaceTemp = new StringBuilder(); Debug.Log("预判" + (lineW + cWidth) + ">" + mLabel.width); if (lineW + cWidth > mLabel.width) { lineW = cWidth; low++; Debug.Log("换行"); if (isface > 0) { spaceTemp.Append("\n") ; Debug.Log("图片换行补换行符"); i += 1; } } else { lineW += cWidth; } if (isface > 0) { FacePostion ePos = new FacePostion(); ePos.facePackID = text[isface + 1]; ePos.faceID = text.Substring(isface + 3, 2); ePos.posX = lineW - faceWidth + m_offsetX; ePos.posY = low * -faceWidth + m_offsetY; eList.Add(ePos); Debug.Log("图:" + ePos.faceID); for (int j = 0; j < spaceCount; j++) spaceTemp.Append(spaceChar); text = text.Remove(isface, faceNamelength); text = text.Insert(isface, spaceTemp.ToString()); i += faceNamelength; } } DrawFace(); }
此方式,终于实现了基本的中文字+图标的混合方式。
但是!
连续的数字、字母宽度,显示的宽度居然会缩减(平均没2个字符减少2像素),经细研究发现,NGUI果然对这些字符做了缩减间距的处理。
不开心!
凭什么UILabel的widget就能获取正常宽度呢,深入探究NGUI源码发现,根源就在以上博文中提起的NGUIText.CalculatePrintedSize()方法。宽度获取失败的原因居然是我没对字体赋值。我服你!
回头又重写,嗯,秉承大神代码我看不懂的原则,最终我实现了完美解决方案。
再次分享在网上以备其它师兄弟备用。看完觉着
public class UILabelTest : MonoBehaviour { UILabel mLabel; UIAtlas faceAtlas; void Awake() { mLabel = GetComponent<UILabel>(); // 动态字体大小赋值(!勿删!) NGUIText.dynamicFont = mLabel.trueTypeFont;//傻逼要先赋值 int charW = (int)(NGUIText.CalculatePrintedSize(spaceChar2.ToString(), true).x); spaceCount = faceWH / charW; if (faceWH % charW != 0) spaceCount += 1; } #region Debug void Start () { string str = mLabel.text; replaceFace4(ref str); mLabel.text = str;} #endregion const int faceNamelength = 5; const char spaceChar2 = ','; int faceWH = 22; int spaceCount = 6; /// <summary> /// 表情偏移 /// </summary> const float m_offsetX = 1; const float m_offsetY = 8; void replaceFace4(ref string text) { if (!string.IsNullOrEmpty(text) && ContainsFace(text)) { mLabel.spacingY = faceWH - mLabel.fontSize; NGUIText.dynamicFont = mLabel.trueTypeFont;//傻逼要先赋值 eList.Clear(); int maxWidth = mLabel.width; float lineW = 0; float lowCount = 0; for (int i = 0; i < text.Length; i++) { if (isFaceLabel(text, i)) { StringBuilder spaceTemp = new StringBuilder(); int isface = i; Vector2 textV = NGUIText.CalculatePrintedSize(text.Substring(0, i),maxWidth, mLabel.fontSize); if (textV.x + faceWH > maxWidth) { //直接下一行 spaceTemp.Append("\n"); i += 1; lineW = 0; lowCount = textV.y + 1; } else { //不换不换就不换 lineW = textV.x; lowCount = textV.y; } FacePostion ePos = new FacePostion(); ePos.facePackID = text[isface + 1]; ePos.faceID = text.Substring(isface + 3, 2); ePos.posX = lineW + m_offsetX; ePos.posY = -lowCount * faceWH + m_offsetY; eList.Add(ePos); spaceTemp.Append("[ffffff00]"); for (int j = 0; j < spaceCount; j++) { spaceTemp.Append(spaceChar2); } spaceTemp.Append("[-]"); text = text.Remove(isface, faceNamelength); text = text.Insert(isface, spaceTemp.ToString()); i += faceNamelength; } } DrawFace(); } } #region 画表情 List<FacePostion> eList = new List<FacePostion>(); List<UISprite> faceSprites = new List<UISprite>(); bool ContainsFace(string text) { return text.Contains("#0_"); } bool isFaceLabel(string text,int index) { return (text[index] == '#' && index + 4 < text.Length && text[index + 2] == '_'); } void DrawFace() { for (int i = 0; i < eList.Count; i++) { UISprite sp = GetSprite(i); sp.gameObject.SetActive(true); sp.spriteName = "#" + eList[i].facePackID + "_" + eList[i].faceID; sp.transform.localPosition = new Vector3(eList[i].posX, eList[i].posY); } for (int i = eList.Count; i < faceSprites.Count; i++) { faceSprites[i].gameObject.SetActive(false); } } UISprite GetSprite(int index) { if (faceSprites.Count >= index) { if (faceAtlas == null) faceAtlas = Resources.Load<UIAtlas>("AtlasImotion/Imotions"); UISprite newsp = NGUITools.AddSprite(this.gameObject, faceAtlas, "", mLabel.depth + 100); newsp.MakePixelPerfect(); newsp.pivot = UIWidget.Pivot.BottomLeft; faceSprites.Add(newsp); return newsp; } else return faceSprites[index]; } class FacePostion { public float posX; public float posY; public char facePackID; public string faceID; } #endregion }
然后就是NGUIText.CalculatePrintedSize的核心代码,加个重载实现。
public static Vector2 CalculatePrintedSize(string text,int maxW,int fontSize) { Vector2 v = new Vector2(0, 1); if (!string.IsNullOrEmpty(text)) { if (encoding) text = StripSymbols(text); Prepare(text); float x = 0f, y = 0f, maxX = 0f; int textLength = text.Length, ch = 0, prev = 0; regionWidth = maxW; finalSize = fontSize; for (int i = 0; i < textLength; ++i) { ch = text[i]; if (ch == '\n') { if (x > maxX) maxX = x; x = 0f; y += 1; continue; } if (ch < ' ') continue; { float w = GetGlyphWidth(ch, prev); if (w != 0f) { w += finalSpacingX; if (Mathf.RoundToInt(x + w) > regionWidth) { if (x > maxX) maxX = x - finalSpacingX; x = w; y += 1; } else x += w; prev = ch; } } } v.x = x; v.y = y + 1; } return v; }
需要注意的地方:
1.uilabel.text必须先赋值,然后再替换才能正确计算字体大小和行大小,所以有表情符号时要赋值2次。
1 0
- Unity3D NGUI图文混排聊天表情
- 【Unity3D游戏开发】基于NGUI的表情图文混排解决方案 (二二)
- 【Unity3D游戏开发】基于NGUI的表情图文混排解决方案 (二二)
- 【Unity3D游戏开发】基于NGUI的表情图文混排解决方案 (二二)
- 【Unity3D游戏开发】基于NGUI的表情图文混排解决方案 (二二)
- AS3聊天表情即图文混排源码
- AS3聊天表情即图文混排源码
- NGUI图文混排
- [Unity3D学习]NGUI UILabel 图文混排扩展
- NGUI之图文混排
- NGUI的图文混排
- unity NGUI图文混排
- Flex: flash聊天框 表情+文字 图文混排 (思路)
- NGUI 图文表情Emoticons
- Android图文混排(QQ表情图像)
- Android - Emoji表情图文混排
- NGUI制作Word图文混排效果
- 类似微信表情图文混排(本地自定义表情)
- 《天下少年英雄》隐私政策
- Python 爬虫笔记(对维基百科页面的深度爬取)
- leetcode 67.Minimum Window Substring
- 利用nodejs express mysql +boostrap构建一个博客
- C语言:逗号运算符和逗号表达式
- Unity3D NGUI图文混排聊天表情
- 进程和线程的区别
- 企业如何运用PRINCE2,避免项目失败——上海信息化培训中心
- 修改TextView中字体的颜色【字符串拼接之后显示在TextView中】
- Activity生命周期
- Android解析XML三种方式(PULL、SAX、DOM)
- 汇编学习笔记(一) -- Hello World!
- Active Shape Models 学习总结(2016.9.27)
- 仿ios键盘效果 点击输入框以外区域键盘消失