1.我用最新的2.3的cocostudio摆了个简单的界面:
继承关系(名字比较乱没改):
2.在cocos2dx lua程序中使用
【加载界面】
用cocostudio导出为csb文件,放到资源目录去,添加该ui代码如下:
-- load csb
local node = cc.CSLoader:createNode('Test.csb')
layer:addChild(node)
【按钮Button】
cocos3.x的版本比较强调用事件来传递消息,减少模块间的耦合。这里gui的处理也基本时给要处理的控件添加事件侦听。
-- btn
local btn = node:getChildByName('btn_ok')
btn:addTouchEventListener(function(sender, state)
-- 2
if state == ccui.TouchEventType.ended then
print('on btn ok')
end
end)
【进度条LoadingBar和复选框CheckBox】
-- loading bar
local loading = node:getChildByName('LoadingBar_1')
-- checkbox
local chk = node:getChildByName('CheckBox_1')
chk:addEventListener(function (sender, type)
-- 0
if type == ccui.CheckBoxEventType.selected then
-- sel
print('sel')
loading:setPercent(50)
else
-- unsel
print('unsel')
loading:setPercent(0)
end
end)
【列表控件ListView】
容器有好几个,ScrollView和PageView都比较容易,这里说下ListView。
ListView可以设置列表项的模型,设置了后可以轻松的克隆多个。他的用处就是美术可以在编辑器里把模板编辑好,程序拿来克隆就行了。如果有多种类型,美术就多摆几个,程序搭框架的时候封装一层设置模型的逻辑来选择用哪个模板,这样也可以实现不同的列表项。具体后面有空可以写些例子。
下面设置模板并创建多个:
-- set item model
local item = list:getChildByName('Image_item')
list:setItemModel(item)
list:removeAllChildren()
for i = 1, 10 do
list:pushBackDefaultItem()
end
我这里的模板是在编辑器里放在listview下的,设置完就移除了(注意移除要用listview来remove,不要removeFromParent)。此时的运行效果如下:
下面我们想要相应按钮按下:
list:addEventListener(function (sender, type)
-- 0
if type == ccui.ListViewEventType.ONSELECTEDITEM_START then
-- sel
print("select child index = ",sender:getCurSelectedIndex())
loading:setPercent(50)
else
-- unsel
print('unsel')
loading:setPercent(0)
end
end)
当按钮刚按下(其实是其touchBegan的时候)的时候是start事件,抬起的时候(即touchEnded)是end事件。这时你会问为何添加的是list的事件,却能在按钮按下的时候收到消息。这是因为他们的基类Widget和ListView做了一些事情。
Widget会在touchBegan之类的触摸处理里向父亲传递该事件:
bool Widget::onTouchBegan(Touch *touch, Event *unusedEvent)
{
_hitted = false;
if (isVisible() && isEnabled() && isAncestorsEnabled() && isAncestorsVisible(this) )
{
_touchBeganPosition = touch->getLocation();
if(hitTest(_touchBeganPosition) && isClippingParentContainsPoint(_touchBeganPosition))
{
_hitted = true;
}
}
if (!_hitted)
{
return false;
}
setHighlighted(true);
/*
* Propagate touch events to its parents
*/
if (_propagateTouchEvents)
{
this->propagateTouchEvent(TouchEventType::BEGAN, this, touch);
}
pushDownEvent();
return true;
}
void Widget::interceptTouchEvent(cocos2d::ui::Widget::TouchEventType event, cocos2d::ui::Widget *sender, Touch *touch)
{
Widget* widgetParent = getWidgetParent();
if (widgetParent)
{
widgetParent->interceptTouchEvent(event,sender,touch);
}
}
这样当一个widget被触摸的时候,他的祖先们都会(有机会)得知他的某个后辈被触摸了。所以这里按钮按下时,listview能收到该事件并处理:
void ListView::interceptTouchEvent(TouchEventType event, Widget *sender, Touch* touch)
{
ScrollView::interceptTouchEvent(event, sender, touch);
if (event != TouchEventType::MOVED)
{
Widget* parent = sender;
while (parent)
{
if (parent && parent->getParent() == _innerContainer)
{
_curSelectedIndex = getIndex(parent);
break;
}
parent = dynamic_cast<Widget*>(parent->getParent());
}
if (sender->isHighlighted()) {
selectedItemEvent(event);
}
}
}
void ListView::selectedItemEvent(TouchEventType event)
{
this->retain();
switch (event)
{
case TouchEventType::BEGAN:
{
if (_listViewEventListener && _listViewEventSelector)
{
(_listViewEventListener->*_listViewEventSelector)(this, LISTVIEW_ONSELECTEDITEM_START);
}
if (_eventCallback) {
_eventCallback(this,EventType::ON_SELECTED_ITEM_START);
}
if (_ccEventCallback)
{
_ccEventCallback(this, static_cast<int>(EventType::ON_SELECTED_ITEM_START));
}
}
break;
default:
{
if (_listViewEventListener && _listViewEventSelector)
{
(_listViewEventListener->*_listViewEventSelector)(this, LISTVIEW_ONSELECTEDITEM_END);
}
if (_eventCallback) {
_eventCallback(this, EventType::ON_SELECTED_ITEM_END);
}
if (_ccEventCallback)
{
_ccEventCallback(this, static_cast<int>(EventType::ON_SELECTED_ITEM_END));
}
}
break;
}
this->release();
}
这样的结果就是只要某个item下的某个按钮被触摸了listview就会收到,所以问题也来了,如果有多个按钮怎么办?上面listview的事件参数只有this(是listview指针)和事件类型,没法知道是哪个按钮被按下了。通过curSel只能得知是哪个item被按下了,需要区分是item下的哪个按钮被按下了,则最好给按钮添加事件处理。
你担心按钮多懒得添加,那么我们就使用模板呗,给模板加事件处理,通过模板克隆的列表项也会有该处理的。将下面这段lua代码添加到设置模板之前:
-- set item callback: we can just add event to model, and diff from curSel
local item0 = list:getItem(0)
local btn_0 = item0:getChildByName('Button_2')
btn_0:addTouchEventListener(function(sender, state)
if state == 2 then
print('on btn test 0')
end
end)
这样就能给每个列表项的按钮添加事件并响应了。所以listview的触摸事件只能用于1个按钮的情况吧(不知后面是否会在事件里加入按钮的参数),多个按钮的话给模板里的该按钮加就行。