【唠叨】
按钮类CCControlButton继承于控件类CCControl。
控件类CCControl主要向子类提供了一系列的控件触发事件。当子控件触发相关的事件后,就会执行相关的控件事件回调函数。这与之前讲的CCMenu中的菜单按钮回调是类似的。
控件类CCControl主要有三个子类:
(1)开关控件CCControlSwitch
(2)滑块控件CCControlSlider
(3)按钮控件CCControlButton
本节讲的是其子类其中之一:按钮类CCControlButton。
【致谢】
http://gl.paea.cn/contents/22933f46650c8213.html
【Demo下载】
https://github.com/shahdza/Cocos_LearningTest/tree/master/demo_%E6%8C%89%E9%92%AE%E6%8E%A7%E4%BB%B6CCControlButton
【3.x】
(1)去掉 “CC”
(2)对象类 CCObject 改为 Ref
(3)按钮事件回调依旧为 cccontrol_selector ,没有使用 CC_CALLBACK_2
(4)按钮状态 CCControlState 改为强枚举 Control::State
// NORMAL //正常 HIGH_LIGHTED //高亮(即在内部触摸状态下) DISABLED //禁用 SELECTED //选中 //
(5)按钮事件 CCControlEvent 改为强枚举 Control::EventType
// TOUCH_DOWN //刚刚开始触摸按钮时 DRAG_INSIDE //在内部拖动时(保持触摸状态下) DRAG_OUTSIDE //在外部拖动时(保持触摸状态下) DRAG_ENTER //拖动刚进入内部时(保持触摸状态下) DRAG_EXIT //拖动刚离开内部时(保持触摸状态下) TOUCH_UP_INSIDE //在内部抬起手指(保持触摸状态下) TOUCH_UP_OUTSIDE //在外部抬起手指(保持触摸状态下) TOUCH_CANCEL //取消触点 //
(6)其他变化不大。
【CCControlButton】
按钮控件CCControlButton,想必大家对这个再熟悉不过了吧?每个游戏基本都会用到按钮。
一个按钮不仅有几种不同的按钮状态,而且还有一些按钮事件。另外按钮控件CCControlButton使用的背景图片是点九图CCScale9Sprite,可以使得按钮在变大的情况下,尽量保持棱角不失真。
1、按钮状态CCControlState
// CCControlStateNormal //正常 CCControlStateHighlighted //高亮(即在内部触摸状态下) CCControlStateDisabled //禁用 CCControlStateSelected //选中 //
2、按钮事件CCControlEvent
// CCControlEventTouchDown //刚刚开始触摸按钮时 CCControlEventTouchDragInside //在内部拖动时(保持触摸状态下) CCControlEventTouchDragOutside //在外部拖动时(保持触摸状态下) CCControlEventTouchDragEnter //拖动刚进入内部时(保持触摸状态下) CCControlEventTouchDragExit //拖动刚离开内部时(保持触摸状态下) CCControlEventTouchUpInside //在内部抬起手指(保持触摸状态下) CCControlEventTouchUpOutside //在外部抬起手指(保持触摸状态下) CCControlEventTouchCancel //取消触点 //
3、绑定按钮事件的方法
// //绑定控件事件 addTargetWithActionForControlEvents(this, cccontrol_selector(HelloWorld::touchDownAction), CCControlEventTouchDown); void addTargetWithActionForControlEvents(CCObject* target, SEL_CCControlHandler action, CCControlEvent controlEvents); //删除控件事件 //removeTargetWithActionForControlEvents(this, cccontrol_selector(HelloWorld::touchDownAction), CCControlEventTouchDown); void removeTargetWithActionForControlEvents(CCObject* target, SEL_CCControlHandler action, CCControlEvent controlEvents); //
4、需要引用的头文件及命名空间
// #include "cocos-ext.h" //包含cocos-ext.h头文件 using namespace cocos2d::extension; //引用cocos2d::extension命名空间 //
5、常用操作如下
// class CCControlButton : public CCControl { /** * 创建CCControlButton的三种方法 */ //使用点九图CCScale9Sprite,按钮中不带标签CCLabel static CCControlButton* create(CCScale9Sprite* sprite); //使用标签label,可以是CCLabelTTF、CCLabelBMFont static CCControlButton* create(CCNode* label, CCScale9Sprite* backgroundSprite); //title:标签内容 //fontName:字体资源,如 "Arial" //fontSize:字体大小,默认 12 //内部创建的标签为CCLabelTTF static CCControlButton* create(std::string title, const char* fontName, float fontSize); /** * 属性设置1(在当前CCControlState下) * getCurrentTitle , getCurrentTitleColor , * TitleLabel , BackgroundSprite , PreferredSize */ //当前显示的标签内容,只读getCurrentTitle CC_SYNTHESIZE_READONLY(CCString*, m_currentTitle, CurrentTitle); //当前显示的标签内容颜色,只读getCurrentTitleColor CC_SYNTHESIZE_READONLY_PASS_BY_REF(ccColor3B, m_currentTitleColor, CurrentTitleColor); //设置当前CCControlState下的标签,set/get CC_SYNTHESIZE_RETAIN(CCNode*, m_titleLabel, TitleLabel); //设置当前CCControlState下的背景精灵,set/get CC_SYNTHESIZE_RETAIN(CCScale9Sprite*, m_backgroundSprite, BackgroundSprite); //设置按钮大小,若标签label大小大于按钮,将自动扩展,set/get。 //不过经过我的测试:设置了,反而按钮大小被固定了。没有按照label的大小进行自动伸展了。 CC_PROPERTY(CCSize, m_preferredSize, PreferredSize); /** * 属性设置2(在指定CCControlState下) * setTitleLabelForState , setTitleForState , setTitleColorForState , * setTitleTTFForState , setTitleTTFSizeForState , * setTitleBMFontForState , * setBackgroundSpriteForState , setBackgroundSpriteFrameForState , getBackgroundSpriteForState */ //设置在指定CCControlState下的 字体标签 //若未设置标签,默认为CCButtonStateNormal状态的字体标签 //字体标签可以是CCLabelTTF、CCLabelBMFont virtual void setTitleLabelForState(CCNode* label, CCControlState state); virtual CCNode* getTitleLabelForState(CCControlState state); //设置在指定CCControlState下的 标签内容 //若未设置标签,默认返回CCButtonStateNormal状态的标签内容 virtual void setTitleForState(CCString* title, CCControlState state); virtual CCString* getTitleForState(CCControlState state); //设置在指定CCControlState下的 标签颜色 virtual void setTitleColorForState(ccColor3B color, CCControlState state); virtual const ccColor3B getTitleColorForState(CCControlState state); //############################################################################### //设置在指定CCControlState下的 标签为CCLabelTTF //fntFile为字体资源名,如 "Arial" virtual void setTitleTTFForState(const char* fntFile, CCControlState state); virtual const char* getTitleTTFForState(CCControlState state); //设置在指定CCControlState下的 CCLabelTTF标签的字体大小 virtual void setTitleTTFSizeForState(float size, CCControlState state); virtual float getTitleTTFSizeForState(CCControlState state); //############################################################################### //设置在指定CCControlState下的 标签为CCLabelBMFont //fntFile为字体资源名,如 *.fnt virtual void setTitleBMFontForState(const char* fntFile, CCControlState state); virtual const char * getTitleBMFontForState(CCControlState state); //############################################################################### //使用点九图CCScale9Sprite,设置在指定CCControlState下的 背景精灵 virtual void setBackgroundSpriteForState(CCScale9Sprite* sprite, CCControlState state); //使用精灵帧CCSpriteFrame,设置在指定CCControlState下的 背景精灵 //其实在内部实现的代码,实际上是利用精灵帧spriteFrame创建了点九图CCScale9Sprite作为背景精灵 virtual void setBackgroundSpriteFrameForState(CCSpriteFrame* spriteFrame, CCControlState state); //获取在指定CCControlState下的 背景图 virtual CCScale9Sprite* getBackgroundSpriteForState(CCControlState state); /** * 继承于父类 */ virtual void setEnabled(bool enabled); //是否启用 virtual void setSelected(bool enabled); //是否选中 virtual void setHighlighted(bool enabled); //是否高亮 }; //
【代码实战】
代码来源于cocos2dx的官方项目TestCpp中。
1、按钮背景(正常、高亮)
2、引入头文件和命名空间
// #include "cocos-ext.h" using namespace cocos2d::extension; //
3、在HelloWorld.h中声明按钮事件的回调函数、显示按钮状态的Label
// CCLabelTTF* displayLabel; //显示按钮状态的label void touchDownAction(CCObject* sender, CCControlEvent controlEvent); //刚刚开始触摸按钮时 void touchDragInsideAction(CCObject* sender, CCControlEvent controlEvent); //在内部拖动时(保持触摸状态下) void touchDragOutsideAction(CCObject* sender, CCControlEvent controlEvent); //在外部拖动时(保持触摸状态下) void touchDragEnterAction(CCObject* sender, CCControlEvent controlEvent); //拖动刚进入内部时(保持触摸状态下) void touchDragExitAction(CCObject* sender, CCControlEvent controlEvent); //拖动刚离开内部时(保持触摸状态下) void touchUpInsideAction(CCObject* sender, CCControlEvent controlEvent); //在内部抬起手指(保持触摸状态下) void touchUpOutsideAction(CCObject* sender, CCControlEvent controlEvent); //在外部抬起手指(保持触摸状态下) void touchCancelAction(CCObject* sender, CCControlEvent controlEvent); //取消触点 //
4、在HelloWorld.cpp的init中创建按钮,并绑定按钮事件
// bool HelloWorld::init() { if ( !CCLayer::init() ) { return false; } //获取可视区域尺寸大小 CCSize mysize = CCDirector::sharedDirector()->getVisibleSize(); //获取可视区域的原点位置 CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin(); //屏幕正中心位置 CCPoint midPos = ccp(mysize.width/2, mysize.height/2); //显示按钮状态的标签displayLabel displayLabel = CCLabelTTF::create("No Event", "Marker Felt", 32); displayLabel->setPosition( midPos + ccp(0, 100) ); this->addChild(displayLabel); //按钮中的背景精灵CCScale9Sprite CCScale9Sprite* bgNormal = CCScale9Sprite::create("btnNormal.png"); //正常背景 CCScale9Sprite* bgHighlighted = CCScale9Sprite::create("btnHighlighted.png"); //高亮背景 //按钮中的标签CCLabelTTF CCLabelTTF* titleNormal = CCLabelTTF::create("Button is Normal !", "Marker Felt", 30); CCLabelTTF* titleHighlighted = CCLabelTTF::create("Button is Highlighted !", "Marker Felt", 30); //创建按钮CCControlButton CCControlButton* btn = CCControlButton::create(titleNormal, bgNormal); btn->setPosition( midPos ); this->addChild(btn); //设置按钮高亮时的状态 btn->setTitleLabelForState(titleHighlighted, CCControlStateHighlighted); //高亮标签 btn->setTitleColorForState(ccRED, CCControlStateHighlighted); //红色 btn->setBackgroundSpriteForState(bgHighlighted, CCControlStateHighlighted); //高亮背景 //写了这句话,反而大小被固定了。没有按照label的大小进行自动伸展了 //btn->setPreferredSize( CCSizeMake(120,40) ); //绑定事件,用于显示按钮状态 btn->addTargetWithActionForControlEvents(this, cccontrol_selector(HelloWorld::touchDownAction), CCControlEventTouchDown); //刚刚开始触摸按钮时 btn->addTargetWithActionForControlEvents(this, cccontrol_selector(HelloWorld::touchDragInsideAction), CCControlEventTouchDragInside); //在内部拖动时(保持触摸状态下) btn->addTargetWithActionForControlEvents(this, cccontrol_selector(HelloWorld::touchDragOutsideAction), CCControlEventTouchDragOutside); //在外部拖动时(保持触摸状态下) btn->addTargetWithActionForControlEvents(this, cccontrol_selector(HelloWorld::touchDragEnterAction), CCControlEventTouchDragEnter); //拖动刚进入内部时(保持触摸状态下) btn->addTargetWithActionForControlEvents(this, cccontrol_selector(HelloWorld::touchDragExitAction), CCControlEventTouchDragExit); //拖动刚离开内部时(保持触摸状态下) btn->addTargetWithActionForControlEvents(this, cccontrol_selector(HelloWorld::touchUpInsideAction), CCControlEventTouchUpInside); //在内部抬起手指(保持触摸状态下) btn->addTargetWithActionForControlEvents(this, cccontrol_selector(HelloWorld::touchUpOutsideAction), CCControlEventTouchUpOutside); //在外部抬起手指(保持触摸状态下) btn->addTargetWithActionForControlEvents(this, cccontrol_selector(HelloWorld::touchCancelAction), CCControlEventTouchCancel); //取消触点 return true; } //
5、实现按钮事件的回调函数
// //刚刚开始触摸按钮时 void HelloWorld::touchDownAction(CCObject *senderz, CCControlEvent controlEvent) { displayLabel->setString("Touch Down"); } //在内部拖动时(保持触摸状态下) void HelloWorld::touchDragInsideAction(CCObject *sender, CCControlEvent controlEvent) { displayLabel->setString("Drag Inside"); } //在外部拖动时(保持触摸状态下) void HelloWorld::touchDragOutsideAction(CCObject *sender, CCControlEvent controlEvent) { displayLabel->setString("Drag Outside"); } //拖动刚进入内部时(保持触摸状态下) void HelloWorld::touchDragEnterAction(CCObject *sender, CCControlEvent controlEvent) { displayLabel->setString("Drag Enter"); } //拖动刚离开内部时(保持触摸状态下) void HelloWorld::touchDragExitAction(CCObject *sender, CCControlEvent controlEvent) { displayLabel->setString("Drag Exit"); } //在内部抬起手指(保持触摸状态下) void HelloWorld::touchUpInsideAction(CCObject *sender, CCControlEvent controlEvent) { displayLabel->setString("Touch Up Inside."); } //在外部抬起手指(保持触摸状态下) void HelloWorld::touchUpOutsideAction(CCObject *sender, CCControlEvent controlEvent) { displayLabel->setString("Touch Up Outside."); } //取消所有触摸 void HelloWorld::touchCancelAction(CCObject *sender, CCControlEvent controlEvent) { displayLabel->setString("Touch Cancel"); } //
6、运行结果
7、分析与总结
(1)本来一个这么小的按钮图片,这么变这么大了呢?这是因为当标签CCLabelTTF的大小大于按钮大小时,按钮就会自动进行伸展。
(2)我明明设置了高亮状态下,标签为titleHighlighted,且其标签内容应该显示“Button is Highlighted ! ”才对呀,为什么还是“Button is Normal”?。。。好吧,这个问题我也不知道。不过字体颜色,和按钮的背景精灵图确实是换掉了。
(3)至于按钮事件:
CCControlEventTouchDragEnter //拖动刚进入内部时(保持触摸状态下)
CCControlEventTouchDragExit //拖动刚离开内部时(保持触摸状态下)
不知道大家有没有观察到呢?因为只有在正好进入或离开按钮内部时才看得到效果,手一抖就变成DragInside或DragOutside了。