zoukankan      html  css  js  c++  java
  • ‎Cocos2d-x 学习笔记(20) ControlButton

    【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", 12), cocos2d::ui::Scale9Sprite::create(),true)

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

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

        Label *label = Label::createWithSystemFont("", "Arial", 30);//
        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 位置均设为按钮长宽一半(居中),并设置可见

  • 相关阅读:
    《学习要像加勒比海盗》读书摘录
    【转载】关于软件测试的几点思考
    黑客与画家 摘录
    基于Jenkins的持续集成CI
    重新开始,整装出发
    java重写equals方法需要注意的几点
    《Google软件测试之道》摘录
    Using sql azure for Elmah
    Invalid object name ‘sys.configurations’. (Microsoft SQL Server, Error: 208)
    Cannot install ubuntu or other linux flavours on citrix Xen server
  • 原文地址:https://www.cnblogs.com/deepcho/p/cocos2dx-controlbutton.html
Copyright © 2011-2022 走看看