cocos2dx 富文本框,支持换行,支持表情(支持汉字截断无乱码)

小工在做了一个游戏聊天功能,里面用到插入表情的富文本和换行的问题;

先看效果,不是你要的效果,可return;(截图由于:输入的问题,未能输入汉字)

实现方式;

定义一个layer,在layer上摆放文本,表情,按钮,等控件,由此来形成一个多控件组成的一个富文本;

表情:仿照QQ,用的是【xy】这种方式来表示,如【00】,对应资源就是00.png

换行:就是是把超出指定宽度的内容回车,实现换行(主要是坐标x=起始位置)当然涉及到表情等,容易出问题;

例子

string m_sString = “待到山花烂漫时,他在花丛中笑【12】丛中笑【12】丛中笑【12】丛中笑【12】”;

下面伪代码实现

处理string 得到string的真实个数长度,一个汉字,一个字母代表一个长度;

创建循环体,分别来遍历没一个汉字或者是字母+特殊字符等,遇到【就判断是否是表情,如果是表情就添加表情,表情添加之前需要将表情之前的汉字等先排列上,表情排列后继续,进行遍历;

如果发现当前遍历的内容所占的屏幕长度就进行换行。表情的长度=getContextSize().width 来获取;

具体实现如代码

void MessageItem::changeLine()

{
CCArray *array = getChildren();
for (int i=0; i<array->count(); i++) {
CCNode* node =(CCNode*) array->objectAtIndex(i);
node->setPositionY(m_iDefaultSize);
}
} void MessageItem::showText(const ccColor3B cColor3B )
{
bool bDoubleLine=false;
int posX= 0;//读取内容的长度小标
int iMsgEnd = 1;
int iMsgStart =1;
int width = m_iPannelWidth ;//显示面板的宽度
std::string r="";
//按照一个汉字一个长度,一个字母或者是特殊符号一个长度,得到的长度;(这样避免换行的时候汉字被分开,出现乱码现象)
int iRealLength = Tools::getRealStringLength(m_TotalMsg);
CCLabelTTF* tempTextView = CCLabelTTF::create();
tempTextView->setFontName("Arial-BoldMT");
tempTextView->setFontSize(24); while( (r= Tools::subString(m_TotalMsg,iMsgStart,iMsgEnd))!= "")
{
//先判断当前读取的字符内容是否是表情
if(r[r.length()-1]=='[')
{
std::string tmp = Tools::subString(m_TotalMsg,iMsgEnd,iMsgEnd+3);
if(tmp[3]==']'&&isNumber(tmp[1])&&isNumber(tmp[2]))//face
{
//表情前面若有内容的处理
if(iMsgEnd-iMsgStart>0)
{
CCLabelTTF* textView = CCLabelTTF::create();
textView->setFontName("Arial-BoldMT");
textView->setFontSize(24);
textView->setColor(cColor3B);
textView->setString(r.substr(0,r.length()-1).c_str());
textView->setPosition(ccp(m_LeftMsg_x+posX, 0));
textView->setAnchorPoint(ccp(0, 0));
posX+=textView->getContentSize().width;
this->addChild(textView); } //如果有表情的处理
char temp[10] = {0};
if(tmp[1]-'0' == 0)
{
sprintf(temp, "%d.png",tmp[2]-'0');
}
else
{
sprintf(temp, "%d%d.png",tmp[1]-'0',tmp[2]-'0');
}
bLineHaveFace = true; CCSprite *sp = CCSprite::create(temp);
sp->setScaleX(0.6);
sp->setScaleY(0.6);
sp->setAnchorPoint(ccp(0, 0));
//如果最后表情在一行的最后的换行处理
if(sp->getContentSize().width+posX>width)
{
posX=0;
if (m_bLimitOneLine == true)
{
break;
}
changeLine();
bDoubleLine=true;
}
iMsgEnd+=4;
iMsgStart=iMsgEnd; sp->setPosition(ccp(m_LeftMsg_x+posX, 0));
posX+=sp->getContentSize().width*0.6; this->addChild(sp);
if(iMsgEnd>iRealLength)
{
break;
}
continue;
}
}
tempTextView->setString(r.c_str());
//如果读取到都是无表情的内容,如下进行换行;
if(tempTextView->getContentSize().width+posX+24 >= width)
{
CCLabelTTF* textView = CCLabelTTF::create();
textView->setFontName("Arial-BoldMT");
textView->setFontSize(24);
textView->setColor(cColor3B);
textView->setString(r.c_str());
textView->setPosition(ccp(m_LeftMsg_x+posX, 0));
textView->setAnchorPoint(ccp(0, 0));
this->addChild(textView);
iMsgEnd++;
iMsgStart=iMsgEnd;
posX=0;
if(iMsgEnd>iRealLength)
{
break;
}
if (m_bLimitOneLine)
{
break;
}
changeLine();
bDoubleLine=true; }
else
{
iMsgEnd++;
if(iMsgEnd>iRealLength)
{
CCLabelTTF* textView = CCLabelTTF::create();
textView->setFontName("Arial-BoldMT");
textView->setColor(cColor3B);
textView->setFontSize(24);
textView->setString(r.c_str());
textView->setPosition(ccp(m_LeftMsg_x+posX, 0));
textView->setAnchorPoint(ccp(0, 0));
this->addChild(textView);
break;
}
}
}
if(bDoubleLine)
{
setContentSize(CCSizeMake(width, m_iDefaultSize*2));
m_pTypeName->setPositionY(m_iDefaultSize);
m_pUserName->setPositionY(m_iDefaultSize);
}
else
{
setContentSize(CCSizeMake(width, m_iDefaultSize));
m_pTypeName->setPositionY(0);
m_pUserName->setPositionY(0);
}
}
// 截取字符,必满乱码的处理;
std::string Tools::subString(std::string str ,int start ,int end)
{
if(typeid(str)==typeid(string) && str.length()>0)
{
int len=str.length(); string tmp=""; //先把str里的汉字和英文分开
vector <string> dump;
int i=0;
while(i<len)
{
if (is_zh_ch(str.at(i))==1)
{
dump.push_back(str.substr(i,3));
i=i+3; }
else
{
dump.push_back(str.substr(i,1));
i=i+1;
}
} int iDumpSize = dump.size();
end=end>0?end:iDumpSize;
if(start<0||start>end)
return "";
for(i=start; i<=end; i++)
{
tmp+=dump[i-1];
}
return tmp;
}
else
{
printf("str is not string\n");
return ""; }
}
//获取字符串的真实长度处理
int Tools::getRealStringLength(std::string str){
int i=0;
int len=str.length();
int r=0;
while(i<len)
{
if (is_zh_ch(str.at(i))==1)
{
r++;
i=i+3; }
else
{
r++;
i=i+1;
}
}
return r; }

如上基本上处理了一个富文本的基本操作,功能比较简单,但是做起来比较容易出问题,像换行,插入表情,截取汉字这个三个问题

cocos2dx 富文本框,支持换行,支持神情(支持汉字截断无乱码)的更多相关文章

  1. selenium 富文本框处理

    selenium 富文本框处理, 网上有用API的解决方法1:参见:http://blog.csdn.net/xc5683/article/details/8963621 群里1位群友的解决方法2:参 ...

  2. H5页面设计器,仿有赞商城页面在线设计器,比富文本框更友好的内容编辑器

    基本上每个web应用,都会牵扯到内容编辑,尤其是移动的web应用,微信开发之类的.页面内容自定义是最常用的功能了,之前大部分解决方案都是采用富文本框编辑器kindeditor,ueditor,cked ...

  3. 常用的富文本框插件FreeTextBox、CuteEditor、CKEditor、FCKEditor、TinyMCE、KindEditor ;和CKEditor实例

    http://www.cnblogs.com/cxd4321/archive/2013/01/30/2883078.html 目前市面上用的比较多的富文本编辑器有: FreeTextBox 一个有很多 ...

  4. Android 富文本框实现 RichEditText

    Android系统自带控件没有富文本框控件,如果想写一封带格式的邮件基本上不可能,EdtiText只有默认一种格式,显示不能滿足要求,!!正好项目需要研究了一下,开发了此控件,现将一些源代码开放一下, ...

  5. 第三百九十五节,Django+Xadmin打造上线标准的在线教育平台—Xadmin集成富文本框

    第三百九十五节,Django+Xadmin打造上线标准的在线教育平台—Xadmin集成富文本框 首先安装DjangoUeditor3模块 Ueditor HTML编辑器是百度开源的HTML编辑器 下载 ...

  6. webdriver高级应用- 操作富文本框

    富文本框的技术实现和普通的文本框的定位存在较大的区别,富文本框的常见技术用到了Frame标签,并且在Frame里面实现了一个完整的HTML网页结构,所以使用普通的定位模式将无法直接定位到富文本框对象. ...

  7. 基于bootstrap的富文本框——wangEditor【欢迎增加开发】

    先来一张效果图: 01. 引言 老早就開始研究富文本框的东西,在写完<深入理解javascript原型与闭包>之后,就想着要去做一个富文本框的插件的样例. 如今网络上开源的富文本框插件许多 ...

  8. kindeditor富文本框,上传文件后,显示文件名称

    kindeditor作为一个应用广泛富文本框,我们经常会利用到它,然而在使用的过程中,发现有的地方使用起来很不方便,例如本文要说的,用户上传文件之后,默认只有文件URL,没有文件说明,如图: 点击确定 ...

  9. selenium向富文本框填写内容的几种方式

    富文本框如果是iframe,则用下 1.先跳转到irame,dr.switchTo().frame(wtext); 然后用js JavascriptExecutor jsExecutor = (Jav ...

随机推荐

  1. jstl中取map,其中map的key是一个对象,value是一个list

    <c:forEach items="${map }" var="item"> //取得key中的属性 ${item.key.name } <c ...

  2. 关于json对象的删除

    摘自:http://xosadan.iteye.com/blog/1100383 关于json对象的删除 一个json对象在后台产生了,但是有些数据可能无效或者不合法,所以需要在前台作些例外处理,比如 ...

  3. [Python爬虫] 之二十九:Selenium +phantomjs 利用 pyquery抓取节目信息信息

    一.介绍 本例子用Selenium +phantomjs爬取节目(http://tv.cctv.com/epg/index.shtml?date=2018-03-25)的信息 二.网站信息 三.数据抓 ...

  4. scrapy-splash抓取动态数据例子六

    一.介绍 本例子用scrapy-splash抓取中广互联网站给定关键字抓取咨询信息. 给定关键字:打通:融合:电视 抓取信息内如下: 1.资讯标题 2.资讯链接 3.资讯时间 4.资讯来源 二.网站信 ...

  5. Android 如何添加一个新的时区

    前言          欢迎大家我分享和推荐好用的代码段~~ 声明          欢迎转载,但请保留文章原始出处:          CSDN:http://www.csdn.net        ...

  6. python的__init__和__new__

    本文所有实例代码在python3.7下 一.__new__和__init__区别 1.__new__先于__init__执行;__new__是相当于其他OOP语言的构造方法,负责创建实例:之后,__i ...

  7. 前端工程化 ESlint 配置

    1.使用的标准 // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style extends ...

  8. 学会使用简单的MySQL操作

    第十八章 学会使用简单的MySQL操作 在前面两个章节中已经介绍过MySQL的安装了.可是光会安装还不够.还须要会一些主要的相关操作.当然了,关于MySQL的内容也是非常多的.仅仅只是对于linux系 ...

  9. 一款实现浏览实事的资讯平台app

    一款实现浏览实事的资讯平台app 如有转载,请注明出处:http://blog.csdn.net/u012301841/article/details/46687447 github链接:https: ...

  10. CodeForces 390E Inna and Large Sweet Matrix(树状数组改段求段)

    树状数组仅仅能实现线段树区间改动和区间查询的功能,能够取代不须要lazy tag的线段树.且代码量和常数较小 首先定义一个数组 int c[N]; 并清空 memset(c, 0, sizeof c) ...