先上图
游戏中常常见到一个富文本的列表,不停地显示游戏相应的消息.每添加一个消息,则向列表底部添加一个项.当消息项超过列表可见区域底部时列表会自动向上移动使最新消息项永远保持在可见区域内.
下面是实现:
var GameMsgList = cc.Node.extend({
ctor : function(view_size) {
this._super();
this.init(view_size);
},
init : function(view_size) {
this._itemData = []; //项数据
this._itemMax = 30; //项上限
this.m_sFonts = "res/fonts/tengxiangyuan.ttf";
this.m_nFontSize = 20;
this.m_pColorDefault = cc.color(255,255,255); //默认颜色
this.m_pColorConfig = {}; //颜色配置,可以外部添加
this.m_pColorConfig.red = cc.color(255,0);
this.m_pColorConfig.green = cc.color(0,0);
this.m_pColorConfig.blue = cc.color(0,255);
this.m_pColorConfig.white = cc.color(255,255);
this.m_pColorConfig.black = cc.color(0,0);
//this.m_pRegExp = new RegExp("<[a-z]+>[\s|\S]+</[a-z]+>");
this.m_pTVSize = view_size;
this.setContentSize(this.m_pTVSize);
this.m_pTView = new ccui.ListView();
this.m_pTView.setDirection(ccui.ScrollView.DIR_VERTICAL);
this.m_pTView.setTouchEnabled(true);
this.m_pTView.setBounceEnabled(true);
this.m_pTView.setItemsMargin(5);
//this.m_pTView.setBackGroundColorType(ccui.Layout.BG_COLOR_SOLID);
//this.m_pTView.setBackGroundColor(cc.color(128,128,128));
//this.m_pTView.setBackGroundColorOpacity(128);
this.m_pTView.setContentSize(this.m_pTVSize);
//this.m_pTView.setScrollBarEnabled(true); //h5 undefined
//this.m_pTView.setScrollBarOpacity(204); //h5 undefined
//this.m_pTView.setScrollBarAutoHideEnabled(false); //h5 undefined
//this.m_pTView.setScrollBarWidth(4); //h5 undefined
//this.m_pTView.setScrollBarColor(cc.color(164,160,122)); //h5 undefined
//this.m_pTView.setScrollBarPositionFromCornerForVertical(cc.p(4,4)); //h5 undefined
this.addChild(this.m_pTView);
},
setColorDefault : function (color) {
this.m_pColorDefault = color;
},
setColor : function (key,color) {
this.m_pColorConfig[key] = color;
},
getColor : function (key) {
var color = this.m_pColorConfig[key];
if (!color) {
return this.m_pColorDefault;
}
return color;
},
setFonts : function (file,size) {
this.m_sFonts = file;
this.m_nFontSize = size;
},
reloadData: function(dataSet) {
var _sourceData = !dataSet ? [] : dataSet;
this._itemData = [];
for(var i = 0,len = _sourceData.length; i < this._itemMax && i < len; ++i) {
var temp = _sourceData[len - i - 1];
this._itemData.push(temp);
}
this._itemData.reverse();
this.reloadItems();
},
reloadItems : function () {
this.m_pTView.removeAllItems();
for(var i = 0,s = this._itemData.length; i < s; ++i) {
this.addItem(this._itemData[i],false);
}
this.m_pTView.jumpToBottom();
},
addItem : function (data,tag) {
var richText = new ccui.RichText();
richText.ignoreContentAdaptWithSize(false);
richText.setContentSize(this.m_pTVSize.width,0);
//richText.setAnchorPoint(cc.p(0,0)); //H5版本默认为(0.5,0)
//parse text
var txt_arr = this.parseText(data.toString());
var txt_arr_len = txt_arr.length;
for(var i = 0; i < txt_arr_len; ++i) {
var txt_obj = txt_arr[i];
//每个数据格式 {text:"***",color:"red"}
var r_text_color = this.getColor(txt_obj.color);
//cc.log("txt_obj.text=1#" + txt_obj.text + "#2");
var r_text = new ccui.RichElementText(i,r_text_color,txt_obj.text,this.m_sFonts,this.m_nFontSize);
richText.pushBackElement(r_text);
}
richText.formatText(); //修改引擎RichText::formatRenderers()
this.m_pTView.pushBackCustomItem(richText);
if(tag) {
this._itemData.push(data);
if(this._itemMax < this._itemData.length) {
this._itemData.splice(0,1);
this.m_pTView.removeItem(0);
}
this.m_pTView.jumpToBottom();
}
},
parseText : function (text) {
var txt_arr = [];
var txt_val_temp = text;
var txt_obj;
var txt_str = "";
while(0 < txt_val_temp.length) {
var ret = txt_val_temp.match(/<[a-z]+>/); //开头
if(ret) {
//KKVS.INFO_MSG(ret[0]);
//KKVS.INFO_MSG(ret["index"]);
//KKVS.INFO_MSG(ret["input"]);
var match_str_start = ret[0];
var match_ind_start = ret["index"];
//cc.log("->匹配头:" + match_str_start + " match_ind_start=" + match_ind_start);
if (0 < match_ind_start) {
txt_str += txt_val_temp.slice(0,match_ind_start);
}
txt_val_temp = txt_val_temp.slice((match_ind_start + match_str_start.length));
if (txt_val_temp.length == 0) {
txt_str += match_str_start;
break;
}
var match_str_key = match_str_start.slice(1,(match_str_start.length - 1));
var match_str_end = "</" + match_str_key + ">";
var end_ret = txt_val_temp.match(match_str_end);
if (end_ret) {
//cc.log("->匹配尾:" + match_str_end);
if(0 < txt_str.length) {
txt_obj = {text : txt_str};
txt_arr.push(txt_obj);
}
var match_ind_end = end_ret["index"];
if(0 < match_ind_end) {
txt_str = txt_val_temp.slice(0,match_ind_end);
txt_obj = {text : txt_str,color : match_str_key};
txt_arr.push(txt_obj);
}
txt_str = "";
txt_val_temp = txt_val_temp.slice((match_ind_end + match_str_end.length));
} else {
txt_str += match_str_start + txt_val_temp;
break;
}
} else {
txt_str += txt_val_temp;
break;
}
}
if(0 < txt_str.length) {
txt_obj = {text : txt_str};
txt_arr.push(txt_obj);
}
return txt_arr;
}
});
示例调用:
var gamemsgsize = cc.size(200,100);
var dataSet = [];
dataSet.push("<red>[系统消息]</red>欢迎<green>骨头专用号</green>进入'奖金牛牛'游戏,祝游戏愉快!");
dataSet.push("<red>[系统消息]</red>游戏结算中...");
dataSet.push("玩家<green>带原子弹的皮卡丘</green>输了2000");
dataSet.push("玩家<green>似雨似雾又似风</green>输了1960");
dataSet.push("<red>[系统消息]</red>游戏已经结束.");
this.m_pGameMsgList = new GameMsgList(gamemsgsize);
this.m_pGameMsgList.reloadData(dataSet);
this.m_pGameMsgList.setPosition(10,10);
sysmsg.addChild(this.m_pGameMsgList);
...
this.m_pGameMsgList.addItem("玩家<green>似雨似雾又似风</green>已经准备",false);
this.m_pGameMsgList.addItem("玩家<green>带原子弹的皮卡丘</green>已经准备",true);
当然,你也可以通过调用下面语句来设置字体:
this.m_pGameMsgList.setFonts("res/.../test.ttf",20);
可以修改默认字体颜色:
this.m_pGameMsgList.setColorDefault(cc.color(128,128));
这样的话,上面的"玩家<green>带原子弹的皮卡丘</green>输了2000"中的"玩家"两个字就不再是默认颜色(白色)了,而是cc.color(128,128).
可以修改配置的字体颜色:
this.m_pGameMsgList.setColor("green",cc.color(128,0));
使用上面语句则使用"玩家<green>带原子弹的皮卡丘</green>输了2000"中的"带原子弹的皮卡丘"几个字不再是原先的绿色了,0).
默认配置中存在的颜色有 red,green,blue,white,black,如果这些颜色满足不了需求,这里允许自由增加配置颜色.如想要增加特定的颜色:
this.m_pGameMsgList.setColor("mycolor_1",cc.color(64,0));
this.m_pGameMsgList.setColor("mycolor_2",64,0));
this.m_pGameMsgList.setColor("mycolor_3",64));
...
可自由定义颜色名字,然后像这样使用它:
this.m_pGameMsgList.addItem("颜色样式:<mycolor_1>颜色1</mycolor_1><mycolor_2>颜色2</mycolor_2><mycolor_3>颜色3</mycolor_3>",true);
补充: UIRichText.cpp中443行添加一句:_customSize.height = newContentSizeHeight;