一.学习笔记

1.开关按钮可以使用MenuItemToggle

local toggleItem = cc.MenuItemToggle:create(cc.MenuItemFont:create("Enabled"), cc.MenuItemFont:create("Disabled"))

 

2.触摸相关

onTouchBegan返回true则可以继续执行onTouchMoved和onTouchEnd

onTouchBegan返回false则此次触摸消息结束,不再执行上述两个方法

setSwallowTouches(true)表示吞掉event,消息不再向底层传递(顶层底层是以zOrder值来看的相对概念)

setSwallowTouches(false)表示消息可以继续传递到下面的层(不常用)

 

ScrollView/TableView存在一个隐蔽的问题(2.x时代不存在)

假如按钮B存在于ScrollView的内容里或TableView的Cell内

当我们在按钮B上方原地完成一次点击后,按钮B绑定的事件响应,这种情况没问题

当我们在按钮B上方按下鼠标并拖动再抬起时,其绑定事件不响应(也正常)

但ScrollView/TableView没有发生拖动事件

即对于ScrollView即其派生类,从其子节点按钮区域发起的拖动无效!

这里的按钮是UIButton

 

解决办法:

对按钮设置setSwallowTouches(false)

从继承关系可以看到

class CC_GUI_DLL Button : public Widget

继续看

void Widget::setSwallowTouches(bool swallow)
{
    if (_touchListener)
    {
        _touchListener->setSwallowTouches(swallow);
    }
}

只要事件继续传递下去,就会有正确的拖动事件

这里的默认值会导致该问题

所以需要手动设置

 

3.模态对话框

local eventDispatcher = self:getEventDispatcher()
eventDispatcher:pauseEventListenersForTarget(self, true)

这样暂停了self对象中所有的消息

因此self无法响应触摸事件

例如self是layerA

调用了pause方法后再create一个popupB

并监听popupB的触摸事件或者按钮事件

这样layerA的事件就被很好的屏蔽了

恢复办法

eventDispatcher:resumeEventListenersForTarget(self, true)

 

另外使用setSwallowTouches的办法也可以屏蔽传递

需要注意的是仅当setSwallowTouches(true)

且onTouchBegan返回true时,才能屏蔽!

可以这样理解,cocos认为这个消息被正确接受了,又被吞了,确实没必要传下去了

 

第一种方法更方便一些

一方面可以随时切换模态非模态

另一方面弹出层也可以不必监听触摸事件,仅处理按钮

 

4.按钮长按

local function touchEvent(sender,eventType)
    if eventType == ccui.TouchEventType.began then
        --鼠标按下

    elseif eventType == ccui.TouchEventType.ended then

        --鼠标抬起

    elseif eventType == ccui.TouchEventType.canceled then

        --取消点击

    end
end

button:addTouchEventListener(touchEvent)

为按钮注册一个这样的事件监听方法

分别要处理鼠标按下 , 鼠标抬起 , 取消点击三种事件

 

鼠标按下:

开始一次计时,使用scheduleScriptFunc(func , 0.5 , false)

这样0.5s后会执行func

func中需要关闭schedule,使用unscheduleScriptEntry

若此时尚未抬起鼠标或取消点击

则此时开启一个新的schedule

执行按下时的重复累加逻辑func1(累加方法,传入)

同时记录下此次点击类型是长按

 

鼠标抬起

首先记录下此次点击结束

其次判断此次点击是否是长按

若是长按,则停止func中开启的schedule

并调用长按结束的回调func2(长按结束方法,传入)

若不是长按,则视为普通单击处理

并调用单击的回调func3(传入)

 

点击取消

这里只需要处理长按的取消

停止func中开启的schedule

并调用长按结束的回调func2

 

这样,我们需要3个方法func1,func2,func3

分别处理长按累加过程,长按结束回调,点击回调三种事件

这样我们的按钮就可以兼容单击和长按

二.坑爹笔记

cocos2.x用了快两年的时间

如今换用cocos3.xlua

遇到了不少坑,这里记录一下

1.cellSizeForTable

cocos2.x返回ccsize(width,height)

cocos3.x返回两个数字height,width 顺序竟然反的?!!

 

2.cocosStudio Node若设置为交互性√会使其作为tablecell的时候无法触摸or滑动

交互性不能打钩

 

3.今天2016/1/12犯了一个低级错误调了整整一上午

在处理一个简单列表界面的时候

ctor方法中定义了

self.tableView = nil

这是一个好的声明习惯,当然不加也不会有问题

但声明的位置位置位置非常重要!!

正确的做法应该是

self.tableView = nil  -- step one

...

self:init()         -- step two

 

在init方法中实例化列表

self.tableView = cc.TableView.create()...

self.tableView:reloadData()

大概是这个样子

 

但如果把第一步和第二步搞反了

很二

但结果确是一个非常隐蔽的错误

init执行之后,会在tableContainer区域先行渲染一部分cell

比方说numberOfCellsInTableView返回10

而一屏只能显示3个cell

在不拉动屏幕的时候,程序就只会渲染这3个

但是但是但是!!

还没等我们拉动,就错误的执行了self.tableView = nil

于是我们创建的tableView就再也访问不到了

同时如果

tableCellAtIndex

numberOfCellsInTableView

都做了nil保护如

if(self.tableView ~= nil)then return 10 end

return 0

那么程序还不会崩溃

只是拉动的时候发现,除了第一屏,后面没东西了

......

调了一上午,希望以后不能再犯这种低级错误

 

4.setOpacity/FadeIn/FadeOut无效问题

Node中属性_cascadeOpacityEnabled默认竟然是false

因此设置透明度时,只处理自己,不递归子节点?!

想要递归子节点需要手动设置setCascadeOpacityEnabled(true)

然而很奇怪的是:cocostudio中创建的节点默认就是true