网上很多例子,我是参考这篇文章:http://www.myexception.cn/operating-system/1591495.html
1.聊天系统难题一:消息需要支持插入表情和换行。
一开始我打算借鉴上面文章中的方法自己用label和image拼接实现自己的富文本,后来同事建议我使用cocos2dx自带的富文本空间RichText,网上找了一些例子学习,在代码中使用发现效果还不错,可以插入图片,也支持自动换行(通过setContentSize(cc.size(width,height))来设置空间的宽高之后,超过宽度的内容就可以自动换行)
RichText使用方法:
local rt = ccui.RichText:create(); rt:ignoreContentAdaptWithSize(false); rt:setContentSize(cc.size(550,120)); --第一个参数是Tag local re1 = ccui.RichElementText:create(1,cc.c3b(255, 255,255), 255,"地瓜与土豆的小清新","Marker Felt",24); --文本 local re2 = ccui.RichElementImage:create(3,cc.c3b(255, 255, 255), 255, "equip/test_icon.png"); --图片 local sp = cc.Sprite:create("equip/test_icon1.png"); local re3 = ccui.RichElementCustomNode:create(4,cc.c3b(255,255,255),255,sp); --自定义 rt:pushBackElement(re1); rt:pushBackElement(re2); rt:pushBackElement(re2); --最后把rt加入到容器中,这里我使用的是listview list:pushBackCustomItem(rt);
2.聊天系统难题二:对消息的格式化处理。
需要对消息字符串进行拆分解析,才能正常提取出消息中的文字和图片。
下面是几个我使用到的字符串处理函数:
--判断字符是否为0到9的数字
function cu:is_number(char) --这里传入的char是通过函数string.byte(字符串,下标)取出的对应字符的整数形式 if char >= 48 and char <= 57 then print("char==number:"..str); return true; end return false; end
--获取字符串的真实长度处理
function cu:getRealStringLength(str) local i = 1; local len = string.len(str); local r = 0; while i<=len do if (self:is_zh_ch(string.byte(str, i))==1) then --这里使用了is_zh_ch()判断是否为中文 r=r+1; i=i+3; else r=r+1; i=i+1; end end return r; end
--判断是否是中文
function cu:is_zh_ch(p) if p < 127 then return 0; else return 1; end end
--截取字符,避免乱码的处理;
function cu:subString(str,start,ends) if string.len(str)>0 then local len = string.len(str); local tmp = ""; --先把str里的汉字和英文分开 local dump = {}; local i = 1; while i<=len do if (cu:is_zh_ch(string.byte(str, i))==1) then table.insert(dump,table.getn(dump)+1,string.sub(str,i,i+2)); i=i+3; else table.insert(dump,table.getn(dump)+1,string.sub(str,i,i)); i=i+1; end end local iDumpSize = table.getn(dump); if ends > 0 then ends = ends; else ends = iDumpSize; end if(start<0 or start>ends) then return ""; end for i = start, ends, 1 do if dump[i]~=nil then tmp = tmp..dump[i]; end end return tmp; else print("str is not string\n"); return ""; end end
--解析消息字符串,将解析后的内容放入RichText返回
function cu:changeToRichText(str) local richtext_ = ccui.RichText:create(); richtext_:ignoreContentAdaptWithSize(false); if cu:getRealStringLength(str) > 25 then richtext_:setContentSize(cc.size(500,60)); else richtext_:setContentSize(cc.size(500,30)); end local iMsgEnd = 1; local iMsgStart = 1; local r = ""; local iRealLength = cu:getRealStringLength(str); local continue = false; while (cu:subString(str,iMsgStart,iMsgEnd) ~= "") do r = cu:subString(str,iMsgStart,iMsgEnd); continue = false; --先判断当前读取的字符内容是否是表情 if(string.sub(r,string.len(r),string.len(r))=='[') then print("有表情"); local tmp = cu:subString(str,iMsgEnd,iMsgEnd+3); print("string.sub(tmp,2,2):"..string.sub(tmp,2,2)); print("string.sub(tmp,3,3):"..string.sub(tmp,3,3)); print("string.sub(tmp,4,4):"..string.sub(tmp,4,4)); if(string.sub(tmp,4,4)==']' and cu:is_number(string.byte(tmp,2)) and cu:is_number(string.byte(tmp,3))) then --face --表情前面若有内容的处理 print("有表情1"); if(iMsgEnd-iMsgStart>0) then -- textView->setString(r.substr(0,r.length()-1).c_str()); local txt_1 = string.sub(r,1,string.len(r)-1); local temp_re_txt = ccui.RichElementText:create(1,cc.c3b(255, 255,255), 255,txt_1,"Marker Felt",24); richtext_:pushBackElement(temp_re_txt); print("字符串1:"..txt_1); end --如果有表情的处理 local temp = {0}; if(string.sub(tmp,2,2)-'0' == 0) then temp = "equip/test_icon"..(string.sub(tmp,3,3)-'0')..".png"; else temp = "equip/test_icon"..(string.sub(tmp,2,2)-'0')..(string.sub(tmp,3,3)-'0')..".png"; end local temp_re_image = ccui.RichElementImage:create(2,cc.c3b(255, 255, 255), 255, "equip/test_icon.png"); -- local temp_re_image = ccui.RichElementImage:create(2,cc.c3b(255, 255, 255), 255, temp); richtext_:pushBackElement(temp_re_image); iMsgEnd = iMsgEnd + 4; iMsgStart = iMsgEnd; if(iMsgEnd>iRealLength) then break; end -- goto next continue = true; end end -- local txt_2 = r; if not continue then if(iMsgEnd>=iRealLength) then break; end iMsgEnd = iMsgEnd+1; end -- iMsgStart=iMsgEnd; -- ::next:: end local txt_2 = cu:subString(str,iMsgStart,iMsgEnd); local temp_re_txt = ccui.RichElementText:create(1,cc.c3b(255, 255,255), 255,txt_2,"Marker Felt",24); richtext_:pushBackElement(temp_re_txt); print("字符串2:"..txt_2); return richtext_; end
tip:对哪种格式的文本是图片完全根据个人喜好制定,不好用常用的聊天符号就行,这里我使用的是[xx](x为0~9的数字)
3.聊天系统难题三:控制发送消息的时间间隔。
需要使用定时器:
--定时器控制发送消息的频率 (参数1是定时器函数 参数2是定时器的循环时间间隔 参数3表示是否循环)
self.ScriptFuncId = CCDirector:sharedDirector():getScheduler():scheduleScriptFunc(self.send_message_scheduler,send_time_interval,false);
--控制发送消息频率定时器函数
function cu:send_message_scheduler()
if_send = true; --在定时器中把标记设置为真,每次发送消息后将标记重新设置回false,通过此标记控制是否可以发送消息
end