【Cocos2d-x 学习笔记 目录链接】

1. 简介

ControlButton实现了按钮功能,根据触摸的位置和移动的过程可识别9中EventType类型,执行对应的回调函数。

直接继承了Control。拥有9种EventType和4种State。

2. create

按钮的创建需要Label和Scale9Sprite。

构造函数:

ControlButton::ControlButton()
: _isPushed(false)
, _parentInited(false)
, _doesAdjustBackgroundImage(false)
, _currentTitleColor(Color3B::WHITE)
, _titleLabel(nullptr)
, _backgroundSprite(nullptr)
, _zoomOnTouchDown(false)
, _marginV(ControlButtonMarginTB)
, _marginH(ControlButtonMarginLR)
{}

有5种重载的create方法

ControlButton* create();
ControlButton* create(cocos2d::ui::Scale9Sprite* sprite);
ControlButton* create(Node* label, cocos2d::ui::Scale9Sprite* backgroundSprite);
ControlButton* create(const std::string& title, const std::string& fontName, float fontSize);
ControlButton* create(Node* label, cocos2d::ui::Scale9Sprite* backgroundSprite, bool adjustBackGroundSize);

- create()

在init()方法中调用initWithLabelAndBackgroundSprite,自动创建了label和Scale9Sprite,

initWithLabelAndBackgroundSprite(Label::createWithSystemFont("", "Helvetica", ), cocos2d::ui::Scale9Sprite::create(),true)

- create(cocos2d::ui::Scale9Sprite* sprite)

因为存在参数Scale9Sprite,最终调用的initWithLabelAndBackgroundSprite仅自动创建了label。

    Label *label = Label::createWithSystemFont("", "Arial", );//
return initWithLabelAndBackgroundSprite(label, sprite,false);

- create(Node* label, cocos2d::ui::Scale9Sprite* backgroundSprite)

因为参数Scale9Sprite和label都存在,直接用它们作为initWithLabelAndBackgroundSprite参数。

initWithLabelAndBackgroundSprite(label, backgroundSprite, true)

- create(const std::string& title, const std::string& fontName, float fontSize)

三个参数是用于创建label的,故最终调用initWithLabelAndBackgroundSprite时,用三个参数创建了label,自动创建了Scale9Sprite

initWithLabelAndBackgroundSprite(Label::createWithSystemFont(title, fontName, fontSize), cocos2d::ui::Scale9Sprite::create(),true)

- create(Node* label, cocos2d::ui::Scale9Sprite* backgroundSprite, bool adjustBackGroundSize)

参数不只提供了Scale9Sprite和label,还提供了adjustBackGroundSize值。

initWithLabelAndBackgroundSprite(label, backgroundSprite, adjustBackGroundSize)

3. initWithLabelAndBackgroundSprite

三个参数:Node* node, ui::Scale9Sprite* backgroundSprite, bool adjustBackGroundSize。

对属性初始化。

_parentInited默认false,在init开始时置true。其为true时,才能执行needsLayout。

4. 回调函数

按钮接收到的单点触摸事件有4种回调函数:

    virtual bool onTouchBegan(Touch *touch, Event *event) override;
virtual void onTouchMoved(Touch *touch, Event *event) override;
virtual void onTouchEnded(Touch *touch, Event *event) override;
virtual void onTouchCancelled(Touch *touch, Event *event) override;

onTouchBegan

1. 判断事件能否接收,满足4个条件才能继续执行,否则返回false,监听器不予处理

    if (!isTouchInside(pTouch) || !isEnabled() || !isVisible() || !hasVisibleParents() )
{
return false;
}
for (Node *c = this->_parent; c != nullptr; c = c->getParent())
{
if (c->isVisible() == false)
{
return false;
}
}

2. 因为开始了触摸,_isPushed置true,setHighlighted(true)

    _isPushed = true;
this->setHighlighted(true);

3. TOUCH_DOWN事件对应的所有函数action被触发,返回true

 说明开始单点触摸时对应的是TOUCH_DOWN事件

    sendActionsForControlEvents(Control::EventType::TOUCH_DOWN);
return true;

setHighlighted(bool enabled)

1. 根据参数是否高亮设置_state。

    if (enabled == true)
{
_state = Control::State::HIGH_LIGHTED;
}
else
{
_state = Control::State::NORMAL;
}

2. 调用父类方法。

    Control::setHighlighted(enabled);

其中,_highlighted被置参数,并调用needsLayout()。

3. 尝试获取缩放动作,存在时停止缩放动作。执行needsLayout()。

 Action *action = getActionByTag(kZoomActionTag);
if (action)
{
stopAction(action);
}
needsLayout();

4. _zoomOnTouchDown表示是否在TouchDown时缩放,默认值true。在_highlighted _enabled为true,_selected为false时使用缩放值_scaleRatio,默认1.1。

 创建了缩放动作,对按钮执行runAction。

    if( _zoomOnTouchDown )
{
float scaleValue = (isHighlighted() && isEnabled() && !isSelected()) ? _scaleRatio : 1.0f;
Action *zoomAction = ScaleTo::create(0.05f, scaleValue);
zoomAction->setTag(kZoomActionTag);
runAction(zoomAction);
}

onTouchMoved

1 . 满足3个条件:_enabled为true,_isPushed为true,_selected为false时,才继续执行,否则结束回调函数。结束前如果_highlighted为true,还要执行setHighlighted(false)。

    if (!isEnabled() || !isPushed() || isSelected())
{
if (isHighlighted())
{
setHighlighted(false);
}
return;
}

2. 判断触摸的坐标在不在按钮范围,设置标志isTouchMoveInside。

    bool isTouchMoveInside = isTouchInside(pTouch);

3. 关键来了,根据触摸是否在触摸范围+是否高亮,分为四种不同的EventType,调用EventType对应的函数action。

    if (isTouchMoveInside && !isHighlighted())
{
setHighlighted(true);
sendActionsForControlEvents(Control::EventType::DRAG_ENTER);
}
else if (isTouchMoveInside && isHighlighted())
{
sendActionsForControlEvents(Control::EventType::DRAG_INSIDE);
}
else if (!isTouchMoveInside && isHighlighted())
{
setHighlighted(false); sendActionsForControlEvents(Control::EventType::DRAG_EXIT);
}
else if (!isTouchMoveInside && !isHighlighted())
{
sendActionsForControlEvents(Control::EventType::DRAG_OUTSIDE);
}

onTouchEnded

1. 因为结束触摸,置标志false。

    _isPushed = false;
setHighlighted(false);

2. 根据结束触摸的点是否在范围里,分为2种EventType,调用对应的回调函数。

    if (isTouchInside(pTouch))
{
sendActionsForControlEvents(Control::EventType::TOUCH_UP_INSIDE);
}
else
{
sendActionsForControlEvents(Control::EventType::TOUCH_UP_OUTSIDE);
}

onTouchCancelled

因为触摸取消,置标志false,此时仅1种EventType,调用对应的回调函数。

    _isPushed = false;
setHighlighted(false);
sendActionsForControlEvents(Control::EventType::TOUCH_CANCEL);

EventType 小结

在按钮内点击:TOUCH_DOWN

在按钮内移动:DRAG_INSIDE

在按钮外移动:DRAG_OUTSIDE

从按钮移出:DRAG_EXIT

从外部移进按钮:DRAG_ENTER

在按钮内结束:TOUCH_UP_INSIDE

在按钮外结束:TOUCH_UP_OUTSIDE

触摸取消:TOUCH_CANCEL

VALUE_CHANGED:触摸拖动或以其他方式控制control,使之有一系列不同的值

5. needsLayout()

对按钮、label、sprite大小颜色文本进行更新的方法,在按钮的一些属性改变时会调用,在修改当前state的label和sprite之后会调用该方法,在按钮init结束之前会调用。

1. 把 label _titleLabel 和 sprite _backgroundSprite 设不可见

2. 给 _titleLabel 设置新锚点 _labelAnchorPoint

3. 通过状态 _state 从label相关的3个容器中获取 label title color,作为 _currentTitle _currentTitleColor _titleLabel,把 _currentTitle _currentTitleColor 设为 _titleLabel 的属性,_titleLabel的位置设为按钮长宽的一半(居中)

4. 通过状态 _state 从sprite容器中获取sprite,作为 _backgroundSprite,_backgroundSprite 位置设为按钮长宽的一半(居中)

5. 如果 _doesAdjustBackgroundImage 为true,_backgroundSprite 的长宽设为label长宽+2*边距(_marginH/_marginV)

6. 如果 _doesAdjustBackgroundImage 为false,且 _backgroundSprite 长宽<=0,label的size作为其size

7. 将按钮大小设为 _backgroundSprite _titleLabel 两者中更大的

8. _backgroundSprite _titleLabel 位置均设为按钮长宽一半(居中),并设置可见

‎Cocos2d-x 学习笔记(20) ControlButton的更多相关文章

  1. Ext.Net学习笔记20:Ext.Net FormPanel 复杂用法

    Ext.Net学习笔记20:Ext.Net FormPanel 复杂用法 在上一篇笔记中我们介绍了Ext.Net的简单用法,并创建了一个简单的登录表单.今天我们将看一下如何更好是使用FormPanel ...

  2. SQL反模式学习笔记20 明文密码

    目标:恢复或重置密码 反模式:使用明文存储密码 1.存储密码 使用明文存储密码或者在网络上传递密码是不安全的. 如果攻击者截取到你用来插入(或者修改)密码的sql语句,就可以获得密码.     黑客获 ...

  3. golang学习笔记20 一道考察对并发多协程操作一个共享变量的面试题

    golang学习笔记20 一道考察对并发多协程操作一个共享变量的面试题 下面这个程序运行的能num结果是什么? package main import ( "fmt" " ...

  4. [原创]java WEB学习笔记20:MVC案例完整实践(part 1)---MVC架构分析

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  5. Hadoop学习笔记—20.网站日志分析项目案例

    1.1 项目来源 本次要实践的数据日志来源于国内某技术学习论坛,该论坛由某培训机构主办,汇聚了众多技术学习者,每天都有人发帖.回帖,如图1所示. 图1 项目来源网站-技术学习论坛 本次实践的目的就在于 ...

  6. Hadoop学习笔记—20.网站日志分析项目案例(三)统计分析

    网站日志分析项目案例(一)项目介绍:http://www.cnblogs.com/edisonchou/p/4449082.html 网站日志分析项目案例(二)数据清洗:http://www.cnbl ...

  7. Linux下汇编语言学习笔记20 ---

    这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...

  8. Hadoop学习笔记—20.网站日志分析项目案例(一)项目介绍

    网站日志分析项目案例(一)项目介绍:当前页面 网站日志分析项目案例(二)数据清洗:http://www.cnblogs.com/edisonchou/p/4458219.html 网站日志分析项目案例 ...

  9. Hadoop学习笔记—20.网站日志分析项目案例(二)数据清洗

    网站日志分析项目案例(一)项目介绍:http://www.cnblogs.com/edisonchou/p/4449082.html 网站日志分析项目案例(二)数据清洗:当前页面 网站日志分析项目案例 ...

随机推荐

  1. python自增自减?赋值语句返回值?逗号表达式?

    咳咳,直接进入正题吧. 自增自减(++/--),以及赋值语句,还有逗号表达式都是在C/C++中常见的运算符或表达式. 熟悉C/C++的小伙伴们都知道,在C/C++中: 自增自减(前缀/后缀)运算符将实 ...

  2. Cabloy-CMS:动静结合,解决Hexo痛点问题(进阶篇)

    前言 前一篇文章 介绍了如何通过Cabloy-CMS快速搭建一个博客站点. 这里简单介绍Cabloy-CMS静态站点的渲染机制,更多详细的内容请参见https://cms.cabloy.com 渲染规 ...

  3. Flink 从 0 到 1 学习 —— 如何自定义 Data Sink ?

    前言 前篇文章 <从0到1学习Flink>-- Data Sink 介绍 介绍了 Flink Data Sink,也介绍了 Flink 自带的 Sink,那么如何自定义自己的 Sink 呢 ...

  4. 03.Django基础三之视图函数

    一 Django的视图函数view 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应. 响应可以是一张网页的HTML内容,一个重定向,一个404错 ...

  5. 【译】Kubernetes监控实践(2):可行监控方案之Prometheus和Sensu

    本文介绍两个可行的K8s监控方案:Prometheus和Sensu.两个方案都能全面提供系统级的监控数据,帮助开发人员跟踪K8s关键组件的性能.定位故障.接收预警. 拓展阅读:Kubernetes监控 ...

  6. [AspNetCore 3.0] 在RazorPages/MVC 中使用 Blazor (Razor组件)

    开发环境 Vs2019 16.3.1 dotnetcore 3.0 一.开始 新建webapp项目 dotnet new webapp -o projectname 或Vs 中新建项目选择 Web应用 ...

  7. 解决行内块元素(inline-block)之间的空格或空白问题

    一.问题产生 由于html代码格式化后,标签会缩进或者换行.由于浏览器默认处理导致元素在页面显示中出现单个空格问题,尤其在行内或者行内块元素布局时影响比较明显 例如: 代码 页面显示 二.解决方案 这 ...

  8. 4.7 if else-if

    c#中的if else-if if else-if  中最后的"else":如果用户输入的不等于上面的else if(xxx)表达式,则输出这行代码. **不参与运算的数值不用转换 ...

  9. Linux环境下实现对文件读写操作

    ---- 今天分享一下在linux系统在实现对文件读写一些基本的操作,在这之前我们要掌握一些基本的技能在Linux环境下.比如查看命令和一个函数的具体用法,就是相当于查手册,在Linux下有一个man ...

  10. ubuntu13 eclipse菜单栏失效解决

    使用ubuntu13安装完eclipse和myeclipse后发现菜单栏单击时不显示下拉框只能通过快捷键显示. 百度了一下,找到以下解决办法. 打开终端运行下面的命令,打开eclipse后可正常显示菜 ...