【cocos2d-x 手游研发小技巧(6)聊天系统+字体高亮】

时间:2023-03-09 00:09:39
【cocos2d-x 手游研发小技巧(6)聊天系统+字体高亮】

转载请注明出处:http://www.cnblogs.com/zisou/p/cocos2dxJQ-6.html

聊天系统在手机网游中是最常见的交互工具,大家在一起边玩游戏边聊天岂不乐哉;

废话不多了,这里重点只介绍客户端的代码,首先输入框肯定用CCEditBox的了,现在这个最好用;

直接贴已经写好的代码:

首先是ChatInput.cpp这个类,主要就是弹出一个输入框,点击后弹出虚拟键盘输入完成后,点击发送的功能;

ChatInput.h

#include "cocos2d.h"
#include "cocos-ext.h"
#include "string"
using namespace std;
USING_NS_CC;
USING_NS_CC_EXT;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS||CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
class ChatInput : public CCLayer, public CCEditBoxDelegate
{
public:
ChatInput();
~ChatInput(); virtual bool init();
CREATE_FUNC(ChatInput); // 需要重写触摸注册函数,重新给定触摸级别
virtual void registerWithTouchDispatcher(void);
// 重写触摸函数,永远返回 true ,屏蔽其它层,达到 “模态” 效果
bool ccTouchBegan(CCTouch *pTouch,CCEvent *pEvent);
void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent); // 构架,并设置对话框背景图片
static ChatInput* create(const char* backgroundImage); //添加输入框
void addEditBox(int tag);
void addEditBox(int tag,int maxlength);
//点击菜单按钮的回调
void buttonCallback(CCObject* pSender); // 为了在显示层时之前的属性生效,选择在 onEnter 里动态展示
virtual void onEnter();
virtual void onExit(); virtual void editBoxEditingDidBegin(cocos2d::extension::CCEditBox* editBox);
virtual void editBoxEditingDidEnd(cocos2d::extension::CCEditBox* editBox);
virtual void editBoxTextChanged(cocos2d::extension::CCEditBox* editBox, const std::string& text);
virtual void editBoxReturn(cocos2d::extension::CCEditBox* editBox); // virtual void keyboardWillShow(cocos2d::CCIMEKeyboardNotificationInfo& info);
// virtual void keyboardDidShow(cocos2d::CCIMEKeyboardNotificationInfo& info);
// virtual void keyboardWillHide(cocos2d::CCIMEKeyboardNotificationInfo& info);
// virtual void keyboardDidHide(cocos2d::CCIMEKeyboardNotificationInfo& info); cocos2d::extension::CCEditBox* m_pEditName; void ShowChangeclass(CCObject *pSender);
void toChangeclass(CCObject *pSender); void sendMsg(CCObject *pSender);
private:
CCSize winSize;
void menuToggleCallback(CCObject* pSender); void togai(float togai); // 文字内容两边的空白区
int m_contentPadding;
int m_contentPaddingTop; CC_SYNTHESIZE_RETAIN(CCMenu*, m__pMenu, MenuButton);
CC_SYNTHESIZE_RETAIN(CCSprite*, m__sfBackGround, SpriteBackGround);
CC_SYNTHESIZE_RETAIN(CCScale9Sprite*, m__s9BackGround, Sprite9BackGround);
CC_SYNTHESIZE_RETAIN(CCLabelTTF*, m__ltTitle, LabelTitle);
CC_SYNTHESIZE_RETAIN(CCLabelTTF*, m__ltContentText, LabelContentText); CC_SYNTHESIZE_RETAIN(CCSprite*, m__sTitle, SpriteTitle); CC_SYNTHESIZE_RETAIN(CCEditBox*, m__pEditBox, EditBox); CCRect thisRect;//弹框的rect
CCRect getRect();
}; #endif

ChatInput.cpp

#include "ChatInput.h"
#include "../GameConfig.h"
#include "../Commen/PublicShowUI.h"
#include "../ImagePaths.h"
#include "../Commen/PublicDoFunc.h"
#include "../GameData/GlobalInfo.h"
#include "../ToDoCommen/ToDoSend.h" #if(CC_TARGET_PLATFORM == CC_PLATFORM_IOS||CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
ChatInput::ChatInput()
:m__pMenu(NULL)
,m_contentPadding()
,m_contentPaddingTop()
,m__sfBackGround(NULL)
,m__s9BackGround(NULL)
,m__ltContentText(NULL)
,m__ltTitle(NULL) ,m__sTitle(NULL)
,m__pEditBox(NULL)
{
winSize = CCDirector::sharedDirector()->getWinSize(); CCLog("ChatInput::ChatInput");
} ChatInput::~ChatInput()
{
CCLog("ChatInput::~ChatInput");
CC_SAFE_RELEASE(m__pMenu);
CC_SAFE_RELEASE(m__sfBackGround);
CC_SAFE_RELEASE(m__s9BackGround);
CC_SAFE_RELEASE(m__ltContentText);
CC_SAFE_RELEASE(m__ltTitle);
CC_SAFE_RELEASE(m__sTitle); } bool ChatInput::init()
{
CCLog("ChatInput::init;");
bool bRef = false;
do
{
CC_BREAK_IF(!CCLayer::init());
this->setContentSize(CCSizeZero);
// 初始化需要的 Menu
CCMenu* menu = CCMenu::create();
menu->setPosition(CCPointZero);
setMenuButton(menu);
setTouchEnabled(true);
bRef = true;
} while ();
return bRef; } void ChatInput::registerWithTouchDispatcher()
{
// 这里的触摸优先级设置为 -128 这保证了,屏蔽下方的触摸
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -, true);
} bool ChatInput::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
return true;
} ChatInput* ChatInput::create(const char *backgroundImage)
{
ChatInput* ml = ChatInput::create();
return ml;
} void ChatInput::addEditBox(int tag,int maxlength)
{
CCEditBox* m_pEditBox = CCEditBox::create(CCSizeMake(, ), CCScale9Sprite::create(p_chat_input_bd));
if(maxlength>)
{
m_pEditBox->setMaxLength(maxlength);
}
m_pEditBox->setReturnType(kKeyboardReturnTypeDone);
m_pEditBox->setDelegate(this); //必须加这一行,否则不能扑捉到editBoxEditingDidBegin等事件
m_pEditBox->setFontColor(ccWHITE);
// m_pEditBox->setText("请输入...");
m_pEditBox->setTag(tag); CCMenuItemImage *button_chatclass = CCMenuItemImage::create(
p_chat_bt_qb0,
p_chat_bt_qb1,
p_chat_bt_qb1,
button_chatclass,
menu_selector(ChatInput::sendMsg));
CCMenu* pMenu_button_chatclass= CCMenu::create(button_chatclass, NULL);
pMenu_button_chatclass->setPosition(ccp(-,m_pEditBox->getContentSize().height/));
m_pEditBox->addChild(pMenu_button_chatclass,, BASEUI_CHAT_CLASS); setEditBox(m_pEditBox); //必须专门设置一次同layer级别一样的优先级,否则不能触发弹出键盘
getEditBox()->setTouchPriority();
} void ChatInput::sendMsg(CCObject *pSender)
{
string nrstr = GlobalInfo::getInstance()->get_chatnrstr();
if(nrstr.length()>)
{
MainRoledata* roleinfo = GlobalInfo::getInstance()->get_mainrole(); // if(roleinfo->user_level>10||roleinfo->User_zhiye=="天仙"||roleinfo->User_zhiye=="金仙")
// {
if(GlobalInfo::getInstance()->get_chatclassname()=="全部")
{
ToDoSend::send_sendMyMsg(CCString::create(""), CCString::create(nrstr.c_str()), CCString::create(roleinfo->Game_UserName), CCString::create(GlobalInfo::getInstance()->get_chatclassname().c_str()), CCString::create(""));
GlobalInfo::getInstance()->set_chat_close_flag(true);
}
else if(GlobalInfo::getInstance()->get_chatclassname()=="天仙")
{
if(roleinfo->User_zhiye=="天仙"||roleinfo->User_zhiye=="金仙")
{
ToDoSend::send_sendMyMsg(CCString::create(""), CCString::create(nrstr.c_str()), CCString::create(roleinfo->Game_UserName), CCString::create(GlobalInfo::getInstance()->get_chatclassname().c_str()), CCString::create(""));
GlobalInfo::getInstance()->set_chat_close_flag(true);
}
else
{
GlobalInfo::getInstance()->set_showtipstring("晋升到天仙以上才能进行天仙传音");
GlobalInfo::getInstance()->set_showtipflag(true);
}
}
else if(GlobalInfo::getInstance()->get_chatclassname()=="金仙")
{
if(roleinfo->User_zhiye=="金仙")
{
ToDoSend::send_sendMyMsg(CCString::create(""), CCString::create(nrstr.c_str()), CCString::create(roleinfo->Game_UserName), CCString::create(GlobalInfo::getInstance()->get_chatclassname().c_str()), CCString::create(""));
GlobalInfo::getInstance()->set_chat_close_flag(true); }
else
{
GlobalInfo::getInstance()->set_showtipstring("晋升到金仙以上才能进行金仙传音");
GlobalInfo::getInstance()->set_showtipflag(true);
}
}
// }
// else
// {
// GlobalInfo::getInstance()->set_showtipstring("修炼到散仙10层才能使用传音功能!");
// GlobalInfo::getInstance()->set_showtipflag(true);
// }
}
else
{
GlobalInfo::getInstance()->set_showtipstring("请输入聊天内容");
GlobalInfo::getInstance()->set_showtipflag(true);
} } void ChatInput::ShowChangeclass(CCObject *pSender)
{
//获取原按钮
CCMenuItemImage *button = (CCMenuItemImage*)pSender; // button->setNormalSpriteFrame(CCSpriteFrame::create(p_chat_bt_tx0, CCRectMake(0, 0, button->getContentSize().width,button->getContentSize().height)));
//全部
if(button->getChildByTag(BASEUI_CHAT_CHANGE_QB)!=NULL)
{
button->removeChildByTag(BASEUI_CHAT_CHANGE_QB);
}
else
{
CCMenuItemImage *button_class_qb= CCMenuItemImage::create(
p_chat_bt_qb0,
p_chat_bt_qb1,
p_chat_bt_qb1,
button_class_qb,
menu_selector(ChatInput::toChangeclass));
button_class_qb->setTag(BASEUI_CHAT_CHANGE_QB);
CCMenu* pMenu_button_qb= CCMenu::create(button_class_qb, NULL);
pMenu_button_qb->setPosition(ccp(button->getContentSize().width/,button->getContentSize().height*1.45));
button->addChild(pMenu_button_qb,, BASEUI_CHAT_CHANGE_QB);
}
//散仙
if(button->getChildByTag(BASEUI_CHAT_CHANGE_SX)!=NULL)
{
button->removeChildByTag(BASEUI_CHAT_CHANGE_SX);
}
else
{
CCMenuItemImage *button_class_sx= CCMenuItemImage::create(
p_chat_bt_sx0,
p_chat_bt_sx1,
p_chat_bt_sx1,
button_class_sx,
menu_selector(ChatInput::toChangeclass));
button_class_sx->setTag(BASEUI_CHAT_CHANGE_SX);
CCMenu* pMenu_button_sx= CCMenu::create(button_class_sx, NULL);
pMenu_button_sx->setPosition(ccp(button->getContentSize().width/,button->getContentSize().height*2.4));
button->addChild(pMenu_button_sx,, BASEUI_CHAT_CHANGE_SX);
}
//天仙
if(button->getChildByTag(BASEUI_CHAT_CHANGE_TX)!=NULL)
{
button->removeChildByTag(BASEUI_CHAT_CHANGE_TX);
}
else
{
CCMenuItemImage *button_class_tx= CCMenuItemImage::create(
p_chat_bt_tx0,
p_chat_bt_tx1,
p_chat_bt_tx1,
button_class_tx,
menu_selector(ChatInput::toChangeclass));
button_class_tx->setTag(BASEUI_CHAT_CHANGE_TX);
CCMenu* pMenu_button_tx= CCMenu::create(button_class_tx, NULL);
pMenu_button_tx->setPosition(ccp(button->getContentSize().width/,button->getContentSize().height*3.4));
button->addChild(pMenu_button_tx,, BASEUI_CHAT_CHANGE_TX);
}
//金仙
if(button->getChildByTag(BASEUI_CHAT_CHANGE_JX)!=NULL)
{
button->removeChildByTag(BASEUI_CHAT_CHANGE_JX);
}
else
{
CCMenuItemImage *button_class_jx= CCMenuItemImage::create(
p_chat_bt_jx0,
p_chat_bt_jx1,
p_chat_bt_jx1,
button_class_jx,
menu_selector(ChatInput::toChangeclass));
button_class_jx->setTag(BASEUI_CHAT_CHANGE_JX);
CCMenu* pMenu_button_jx= CCMenu::create(button_class_jx, NULL);
pMenu_button_jx->setPosition(ccp(button->getContentSize().width/,button->getContentSize().height*4.4));
button->addChild(pMenu_button_jx,, BASEUI_CHAT_CHANGE_JX);
}
} void ChatInput::togai(float togai)
{
// this->getChildByTag(BASEUI_CHAT_CLASS)->setVisible(false);
if(GlobalInfo::getInstance()->get_todo_changeChatClass_flag()==true)
{ CCPoint nowp = this->getChildByTag(BASEUI_CHAT_CLASS)->getPosition();
this->removeChildByTag(BASEUI_CHAT_CLASS);
if(GlobalInfo::getInstance()->get_todo_changeChatClass_int()==BASEUI_CHAT_CHANGE_SX)
{
CCMenuItemImage *button_class_sx= CCMenuItemImage::create(
p_chat_bt_sx0,
p_chat_bt_sx1,
p_chat_bt_sx1,
this,
menu_selector(ChatInput::ShowChangeclass));
CCMenu* pMenu_button_sx= CCMenu::create(button_class_sx, NULL);
pMenu_button_sx->setPosition(nowp);
this->addChild(pMenu_button_sx,, BASEUI_CHAT_CLASS);
}
else if(GlobalInfo::getInstance()->get_todo_changeChatClass_int()==BASEUI_CHAT_CHANGE_QB)
{
CCMenuItemImage *button_class_qb= CCMenuItemImage::create(
p_chat_bt_qb0,
p_chat_bt_qb1,
p_chat_bt_qb1,
this,
menu_selector(ChatInput::ShowChangeclass));
CCMenu* pMenu_button_qb= CCMenu::create(button_class_qb, NULL);
pMenu_button_qb->setPosition(nowp);
this->addChild(pMenu_button_qb,, BASEUI_CHAT_CLASS);
}
else if(GlobalInfo::getInstance()->get_todo_changeChatClass_int()==BASEUI_CHAT_CHANGE_TX)
{
CCMenuItemImage *button_class_tx= CCMenuItemImage::create(
p_chat_bt_tx0,
p_chat_bt_tx1,
p_chat_bt_tx1,
this,
menu_selector(ChatInput::ShowChangeclass));
CCMenu* pMenu_button_tx= CCMenu::create(button_class_tx, NULL);
pMenu_button_tx->setPosition(nowp);
this->addChild(pMenu_button_tx,, BASEUI_CHAT_CLASS);
}
else if(GlobalInfo::getInstance()->get_todo_changeChatClass_int()==BASEUI_CHAT_CHANGE_JX)
{
CCMenuItemImage *button_class_jx= CCMenuItemImage::create(
p_chat_bt_jx0,
p_chat_bt_jx1,
p_chat_bt_jx1,
this,
menu_selector(ChatInput::ShowChangeclass));
CCMenu* pMenu_button_jx= CCMenu::create(button_class_jx, NULL);
pMenu_button_jx->setPosition(nowp);
this->addChild(pMenu_button_jx,, BASEUI_CHAT_CLASS);
} GlobalInfo::getInstance()->set_todo_changeChatClass_flag(false);
} } void ChatInput::toChangeclass(CCObject *pSender)
{
CCNode * nd = (CCNode*)pSender;
int TAGS = nd->getTag();
if(TAGS==BASEUI_CHAT_CHANGE_SX)
{
GlobalInfo::getInstance()->set_chatclassname("散仙");
}
else if(TAGS==BASEUI_CHAT_CHANGE_QB)
{
GlobalInfo::getInstance()->set_chatclassname("全部");
}
else if(TAGS==BASEUI_CHAT_CHANGE_TX)
{
GlobalInfo::getInstance()->set_chatclassname("天仙");
}
else if(TAGS==BASEUI_CHAT_CHANGE_JX)
{
GlobalInfo::getInstance()->set_chatclassname("金仙");
}
GlobalInfo::getInstance()->set_todo_changeChatClass_flag(true);
GlobalInfo::getInstance()->set_todo_changeChatClass_int(nd->getTag());
} void ChatInput::addEditBox(int tag)
{
GlobalInfo::getInstance()->set_chatclassname("全部");
CCEditBox* m_pEditBox = CCEditBox::create(CCSizeMake(, ), CCScale9Sprite::create(p_chat_input_bd));
m_pEditBox->setMaxLength();
m_pEditBox->setReturnType(kKeyboardReturnTypeDone);
m_pEditBox->setDelegate(this); //必须加这一行,否则不能扑捉到editBoxEditingDidBegin等事件
m_pEditBox->setFontColor(ccWHITE);
// m_pEditBox->setText("请输入...");
// m_pEditBox->setFontSize(5);
m_pEditBox->setTag(tag);
//设置键盘输入模式
m_pEditBox->setInputMode(kEditBoxInputModeAny); CCMenuItemImage *button_chatclass = CCMenuItemImage::create(
p_chat_bt_qb0,
p_chat_bt_qb1,
p_chat_bt_qb1,
this,
menu_selector(ChatInput::ShowChangeclass));
CCMenu* pMenu_button_chatclass= CCMenu::create(button_chatclass, NULL);
pMenu_button_chatclass->setPosition(ccp(-button_chatclass->getContentSize().width*0.5,m_pEditBox->getContentSize().height/));
m_pEditBox->addChild(pMenu_button_chatclass,, BASEUI_CHAT_CLASS); CCMenuItemImage *button_send = CCMenuItemImage::create(
p_caozuo_send0,
p_caozuo_send1,
p_caozuo_send1,
button_chatclass,
menu_selector(ChatInput::sendMsg));
CCMenu* pMenu_button_send= CCMenu::create(button_send, NULL);
pMenu_button_send->setPosition(ccp(m_pEditBox->getContentSize().width*1.15,m_pEditBox->getContentSize().height/));
m_pEditBox->addChild(pMenu_button_send,, BASEUI_CHAT_SEND); setEditBox(m_pEditBox); m_pEditBox->schedule(schedule_selector(ChatInput::togai)); //必须专门设置一次同layer级别一样的优先级,否则不能触发弹出键盘
getEditBox()->setTouchPriority(-);
} void ChatInput::buttonCallback(CCObject *pSender){
// CCNode* node = dynamic_cast<CCNode*>(pSender);
// CCLog("menubutton tag: %d", node->getTag());
// if(node->getTag()==LAYER_HALL_EDITBOX_SEND){
// CCLog("发送:%s len=%d",getEditBox()->getText(),strlen(getEditBox()->getText()));
// const char* text = getEditBox()->getText();
// if(strlen(text)>0)
// {
// CCArray *data = CCArray::create();
// data->addObject(CCString::create(text));
// SocketThread::sharedSocketThread()->Send(EVENT_LOUDChatInput,data);
// }
// }else{
// CCLog("关闭");
// }
// if (m_callback && m_callbackListener){
// CCLog("调用注册函数");
// (m_callbackListener->*m_callback)();
// }
// this->removeFromParentAndCleanup(true);
} void ChatInput::onEnter()
{
CCLayer::onEnter(); CCSize winSize = CCDirector::sharedDirector()->getWinSize(); CCSize contentSize = getContentSize(); // 显示EditBox
if (getEditBox())
{
CCSprite* ChatInputBg= CCSprite::create(p_login_zhanghu);
getEditBox()->setAnchorPoint(CCPointZero);
getEditBox()->setPosition(ccp(ChatInputBg->getPositionX(),ChatInputBg->getPositionY()+ChatInputBg->getContentSize().height+2.0f));
this->addChild(getEditBox());
} // 添加按钮,并设置其位置
if (getMenuButton()->getChildrenCount()>)
{
// CCLog("size=%d",getMenuButton()->getChildrenCount());
float btnWidth = 100.0;
// CCLog("btnwidth=%f",btnWidth);
CCArray* array = getMenuButton()->getChildren();
CCObject* pObj = NULL;
int i = ;
CCARRAY_FOREACH(array, pObj)
{
CCNode* node = (CCNode*) pObj;
switch(i){
case :
// CCLog("btn width=%f",node->getContentSize().width);
node->setAnchorPoint(CCPointZero);
node->setPosition(ccp(getEditBox()->getPositionX()+getEditBox()->getContentSize().width + 2.0f , getEditBox()->getPositionY()));
break;
case :
node->setPosition(ccp(getEditBox()->getPositionX()+ , getEditBox()->getPositionY()));
break;
}
i++;
}
this->addChild(getMenuButton());
} thisRect = getRect(); } void ChatInput::editBoxEditingDidBegin(cocos2d::extension::CCEditBox* editBox)
{
CCLog("editBox %p DidBegin !", editBox);
// editBox->setText("");
} void ChatInput::editBoxEditingDidEnd(cocos2d::extension::CCEditBox* editBox)
{
CCLog("editBox %p DidEnd !", editBox);
} void ChatInput::editBoxTextChanged(cocos2d::extension::CCEditBox* editBox, const std::string& text)
{
CCLog("editBox %p TextChanged, text: %s ", editBox, text.c_str());
GlobalInfo::getInstance()->set_chatnrstr(text.c_str());
} void ChatInput::editBoxReturn(cocos2d::extension::CCEditBox* editBox)
{
CCLog("->>>>>>>>>>>>>>>>> %d ",editBox->getTag()); // CCArray* arraylist = CCArray::create();
// arraylist->addObject(editBox);
// arraylist->addObject(CCString::create(editBox->getText()));
if(editBox->getTag()==INPUT_NAME)
{
GlobalInfo::getInstance()->set_inputname_str(editBox->getText());
}
else
{
// PublicDoFunc::toDoFuncN(LAYER_LOGIN,callfuncN_selector(LoginScenes::set_input_zhanghu),(CCNode*)editBox);
}
} CCRect ChatInput::getRect()
{
//获取精灵区域大小
return CCRectMake(getEditBox()->getPositionX()- getEditBox()->getContentSize().width * getEditBox()->getAnchorPoint().x,getEditBox()->getPositionY()-getEditBox()->getContentSize().height* getEditBox()->getAnchorPoint().y,getEditBox()->getContentSize().width+50.0f, getEditBox()->getContentSize().height);
} void ChatInput::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
CCPoint point = pTouch->getLocation();
// CCLog("%f,%f",thisRect.size.width,thisRect.size.height);
point = this->convertToNodeSpace(point);
if(this->thisRect.containsPoint(point)==false)
{
//播放点击音效
this->removeFromParentAndCleanup(true);
}
} void ChatInput::onExit()
{
CCLog("ChatInput::onExit");
CCLayer::onExit();
}
#endif

Ok,有了输入框,下面重要的就是聊天界面了,大家都知道,通常普通的CCLabelTTF是很难实现和帮助我们完成

大量的自定义界面,字体渲染工作的(在3.0以前,目前3.0以上已经可以很好处理字体渲染,阴影等问题)。那么

我们就得做类似自定义的控件了,而且要作可插拔的控件。

接着我们说一下实现原理,图示:

【cocos2d-x 手游研发小技巧(6)聊天系统+字体高亮】

图中主要用到了CCTableView,图中有很多小细节需要去细化和完成,比如说:聊天显示方式,下面的往往是

最后一条聊天信息,那就需要执行一下将最下面的一条信息设置为最下面;还有Cell里面的内容信息需要去

拼凑字符集去显示!

先上代码;

自定义TableView类 ChatTableView.h:

#ifndef _ChatTableView_
#define _ChatTableView_ #include "cocos-ext.h"
#include "cocos2d.h"
#include "string"
#include "../GameData/Msgdata.h" using namespace std; USING_NS_CC;
USING_NS_CC_EXT; class ChatTableView :public CCLayer,CCTableViewDataSource,CCTableViewDelegate
{
public: vector<Msgdata> n_msglist; float n_w,n_h,one_h;
CCTableView* pTableView; ChatTableView(CCSprite* sp,float w,float h,vector<Msgdata> msglist);
~ChatTableView(void); virtual void tableCellTouched(cocos2d::extension::CCTableView* table, cocos2d::extension::CCTableViewCell* cell); virtual cocos2d::CCSize cellSizeForTable(cocos2d::extension::CCTableView *table); virtual cocos2d::extension::CCTableViewCell* tableCellAtIndex(cocos2d::extension::CCTableView *table, unsigned int idx); virtual unsigned int numberOfCellsInTableView(cocos2d::extension::CCTableView *table);
virtual CCSize tableCellSizeForIndex(CCTableView* table,unsigned int idx);
virtual void scrollViewDidScroll(cocos2d::extension::CCScrollView* view){};
virtual void scrollViewDidZoom(cocos2d::extension::CCScrollView* view); //高亮显示。选中效果
virtual void tableCellHighlight(CCTableView* table, CCTableViewCell* cell); /**
* Delegate to respond a table cell release event
*
* @param table table contains the given cell
* @param cell cell that is pressed
*/
virtual void tableCellUnhighlight(CCTableView* table, CCTableViewCell* cell); private: }; #endif //_TIPS_FOR_STORY_

ChatTableView.cpp:

#include "ChatTableView.h"
#include "../ImagePaths.h"
#include "../VisibleRect.h"
#include "../Commen/PublicShowUI.h"
#include "../Commen/FontChina.h"
#include "../GameConfig.h"
#include "../Commen/PublicDoFunc.h"
#include "../GameData/GlobalInfo.h"
#include "../HttpCommen/HttpWebServer.h"
#include "../ServerAPI.h" ChatTableView::ChatTableView(CCSprite* sp,float w,float h,vector<Msgdata> msglist)
{
if(sp->getChildByTag()!=NULL)
{
sp->removeChildByTag();
}
n_w=w;
n_h=h;
one_h=;
n_msglist=msglist; pTableView= CCTableView::create(this, VisibleRect::getVisibleRect().size,NULL);
pTableView->setDirection(kCCScrollViewDirectionVertical); pTableView->setDelegate(this);
pTableView->setPosition(ccp(sp->getContentSize().width*0.04,sp->getContentSize().height*0.14));
pTableView->reloadData();
pTableView->setViewSize(CCSizeMake(sp->getContentSize().width*0.94,sp->getContentSize().height*0.80));
pTableView->setContentSize(CCSizeMake(sp->getContentSize().width*0.94,sp->getContentSize().height*0.80));
sp->addChild(pTableView,,);
} void ChatTableView::tableCellTouched(cocos2d::extension::CCTableView* table, cocos2d::extension::CCTableViewCell* cell)
{
CCLog("tableCellTouched"); } CCSize ChatTableView::cellSizeForTable(cocos2d::extension::CCTableView *table)
{
//计算出高度
//
// CCSize cellSize =CCSizeMake(n_w, 60);
return CCSizeMake(, );
}
CCSize ChatTableView::tableCellSizeForIndex(CCTableView* table,unsigned int idx)
{
// CCLOG("size forindex==%d",idx);
if(idx < n_msglist.size()-)
{
idx += ;
}
Msgdata ms;
string chatnr = n_msglist.at(idx).MsgText;
string ss1s = chatnr; int higth=-;
if(chatnr.size()>)
{
higth=;
}
else
{
higth=;
}
return CCSizeMake(n_w,higth);
}
CCTableViewCell* ChatTableView::tableCellAtIndex(cocos2d::extension::CCTableView *table, unsigned int idx)
{
CCTableViewCell *pcell = table->dequeueCell();
if (!pcell)
{
pcell = new CCTableViewCell();
pcell->autorelease();
} pcell->removeAllChildren(); Msgdata ms;
string playername = n_msglist.at(idx).MyInfo;
string chattype = n_msglist.at(idx).MsgType;
string chatnr = n_msglist.at(idx).MsgText; chattype = "["+chattype+"]";
playername = playername+":";
CCLabelTTF* tf = CCLabelTTF::create(chattype.c_str(), "", );
tf->setHorizontalAlignment(kCCTextAlignmentLeft); //对齐
tf->setColor(ccc3(, , ));
tf->setAnchorPoint(CCPointZero);
pcell->addChild(tf);
CCLabelTTF* tf2 = CCLabelTTF::create(playername.c_str(), "", );
tf2->setHorizontalAlignment(kCCTextAlignmentLeft); //对齐
tf2->setColor(ccc3(, , ));
tf2->setPosition(ccp(tf->getContentSize().width+tf2->getContentSize().width/*1.1,tf->getContentSize().height/));
pcell->addChild(tf2); string st1,st2,st3;
if(chatnr.size()>)
{
st1 = chatnr.substr(,);
st2 = chatnr.substr(,chatnr.size());
CCLabelTTF* tf3 = CCLabelTTF::create(st1.c_str(), "", );
tf3->setHorizontalAlignment(kCCTextAlignmentLeft); //对齐
tf3->setColor(ccc3(, , ));
tf3->setPosition(ccp(tf->getContentSize().width+tf2->getContentSize().width+tf3->getContentSize().width/,tf->getContentSize().height/));
pcell->addChild(tf3);
if(st2.size()>)
{
CCLabelTTF* tf4 = CCLabelTTF::create(st2.c_str(), "", );
tf4->setHorizontalAlignment(kCCTextAlignmentLeft); //对齐
tf4->setColor(ccc3(, , ));
tf4->setPosition(ccp(tf->getPosition().x,tf->getPosition().y-tf4->getContentSize().height/*1.3));
pcell->addChild(tf4);
} }
else
{
CCLabelTTF* tf3 = CCLabelTTF::create(chatnr.c_str(), "", );
tf3->setHorizontalAlignment(kCCTextAlignmentLeft); //对齐
tf3->setColor(ccc3(, , ));
tf3->setPosition(ccp(tf->getContentSize().width+tf2->getContentSize().width+tf3->getContentSize().width/,tf->getContentSize().height/));
pcell->addChild(tf3);
} playername.clear();
chattype.clear();
chatnr.clear();
if(idx==n_msglist.size())
{
n_msglist.clear();
} return pcell;
} unsigned int ChatTableView::numberOfCellsInTableView(cocos2d::extension::CCTableView *table)
{
int count = -;
if(n_msglist.size()>)
{
count =n_msglist.size();
}
else
{
count = ;
}
return count;
} void ChatTableView::scrollViewDidZoom(cocos2d::extension::CCScrollView* view)
{
CCLOG("didzoom");
} void ChatTableView::tableCellHighlight(CCTableView* table, CCTableViewCell* cell)
{ // CCSprite* note = (CCSprite*)cell->getChildByTag(1);
// CCMenuItemImage* image = (CCMenuItemImage*)note->getChildByTag(1);
// image->selected();
CCLOG("高亮");
} /**
* Delegate to respond a table cell release event
*
* @param table table contains the given cell
* @param cell cell that is pressed
*/
void ChatTableView::tableCellUnhighlight(CCTableView* table, CCTableViewCell* cell)
{
// CCSprite* note = (CCSprite*)cell->getChildByTag(1);
// CCMenuItemImage* image = (CCMenuItemImage*)note->getChildByTag(1);
// image->unselected(); CCLOG("不高亮");
} ChatTableView::~ChatTableView(void)
{ }

其中重要的设定Cell高度的tableCellSizeForIndex方法如下,需要多加一行,不然会错乱:

CCSize ChatTableView::tableCellSizeForIndex(CCTableView* table,unsigned int idx)
{
if(idx < n_msglist.size()-)
{
idx += ;
}int higth=-;
if(chatnr.size()>)
{
higth=;
}
else
{
higth=;
}
return CCSizeMake(n_w,higth);
}

自己拼装的换行的方法,大家可以自己去写自己的一套,原理思路就是这样,没多大变化,

主要就是计算各种坐标和字体长度:

    Msgdata ms;
string playername = n_msglist.at(idx).MyInfo;
string chattype = n_msglist.at(idx).MsgType;
string chatnr = n_msglist.at(idx).MsgText;
chattype = "["+chattype+"]";
playername = playername+":";
CCLabelTTF* tf = CCLabelTTF::create(chattype.c_str(), "", );
tf->setHorizontalAlignment(kCCTextAlignmentLeft); //对齐
tf->setColor(ccc3(, , ));
tf->setAnchorPoint(CCPointZero);
pcell->addChild(tf);
CCLabelTTF* tf2 = CCLabelTTF::create(playername.c_str(), "", );
tf2->setHorizontalAlignment(kCCTextAlignmentLeft); //对齐
tf2->setColor(ccc3(, , ));
tf2->setPosition(ccp(tf->getContentSize().width+tf2->getContentSize().width/*1.1,tf->getContentSize().height/));
pcell->addChild(tf2); string st1,st2,st3;
if(chatnr.size()>)
{
st1 = chatnr.substr(,);
st2 = chatnr.substr(,chatnr.size());
CCLabelTTF* tf3 = CCLabelTTF::create(st1.c_str(), "", );
tf3->setHorizontalAlignment(kCCTextAlignmentLeft); //对齐
tf3->setColor(ccc3(, , ));
tf3->setPosition(ccp(tf->getContentSize().width+tf2->getContentSize().width+tf3->getContentSize().width/,tf->getContentSize().height/));
pcell->addChild(tf3);
if(st2.size()>)
{
CCLabelTTF* tf4 = CCLabelTTF::create(st2.c_str(), "", );
tf4->setHorizontalAlignment(kCCTextAlignmentLeft); //对齐
tf4->setColor(ccc3(, , ));
tf4->setPosition(ccp(tf->getPosition().x,tf->getPosition().y-tf4->getContentSize().height/*1.3));
pcell->addChild(tf4);
} }
else
{
CCLabelTTF* tf3 = CCLabelTTF::create(chatnr.c_str(), "", );
tf3->setHorizontalAlignment(kCCTextAlignmentLeft); //对齐
tf3->setColor(ccc3(, , ));
tf3->setPosition(ccp(tf->getContentSize().width+tf2->getContentSize().width+tf3->getContentSize().width/,tf->getContentSize().height/));
pcell->addChild(tf3);
} playername.clear();
chattype.clear();
chatnr.clear();
if(idx==n_msglist.size())
{
n_msglist.clear();
}

最后就是将这些写好的小控件都展示出来了!画背景,然后把TableView装载进去了;

void ChatTips::updata_msglist()
{
     vector<Msgdata> msgdatalist_qb;
//先解析出所有信息
string spstr = "⊙";
vector<string> strlist = PublicCommen::split(GlobalInfo::getInstance()->get_chatreturnstr(),spstr);
if(strlist.at().length()>)
{
msgdatalist_qb = JsonPush::ToGetMsgListdata(strlist.at());
ChatTableView *tableview = new ChatTableView(this,this->getContentSize().width*0.9,this->getContentSize().height*0.9,msgdatalist_qb);
tableview->pTableView->setContentOffset(ccp(,this->getContentSize().height*0.05));
}
msgdatalist_qb.clear();
strlist.clear();
}

显示的时候注意要将最后一条聊天信息展示出来,用setContentOffset这个方法:

tableview->pTableView->setContentOffset(ccp(,this->getContentSize().height*0.05));

好了以上就是最核心部分,下面我贴图上我游戏里面的聊天效果:

【cocos2d-x 手游研发小技巧(6)聊天系统+字体高亮】

【cocos2d-x 手游研发小技巧(6)聊天系统+字体高亮】

【cocos2d-x 手游研发小技巧(6)聊天系统+字体高亮】

【cocos2d-x 手游研发小技巧(6)聊天系统+字体高亮】

下一篇我将介绍使用Lua做功能模块更新拓展的技巧文章;

—————————————————————————————————————————————————————————————

ps:仙凡奇缘官网 http://www.xianfancoco.com

仙凡奇缘开发版1.0已上线:百度云盘下载体验

cocos2dxQQ交流群:41131516