CocoStudio UIButton setPressedActionEnabled 子控件缩放解决方案

为什么子控件不跟着缩放

  • UIButton是个组合的控件,其主体是个Widget,里面有如下几个子控件:

    Scale9Sprite* _buttonNormalRenderer;
    Scale9Sprite* _buttonClickedRenderer;
    Scale9Sprite* _buttonDisabledRenderer;
    Label* _titleRenderer;
  • 设置setPressedActionEnabled为true之后,主要的处理在onPressStateChangedToNormal和onPressStateChangedToPressed两个函数中,(基于v3.14.1)代码如下:

void Button::onPressStateChangedToNormal()
{
    _buttonNormalRenderer->setVisible(true);
    _buttonClickedRenderer->setVisible(false);
    _buttonDisabledRenderer->setVisible(false);
    _buttonNormalRenderer->setState(Scale9Sprite::State::NORMAL);

    if (_pressedTextureLoaded)
    {
        if (_pressedActionEnabled)
        {
            // 以下为操作代码
            _buttonNormalRenderer->stopAllActions();
            _buttonClickedRenderer->stopAllActions();

//            Action *zoomAction = ScaleTo::create(ZOOM_ACTION_TIME_STEP, _normalTextureScaleXInSize, _normalTextureScaleYInSize);
            //fixme: the zoomAction will run in the next frame which will cause the _buttonNormalRenderer to a wrong scale
            _buttonNormalRenderer->setScale(1.0);
            _buttonClickedRenderer->setScale(1.0);

            if (nullptr != _titleRenderer)
            {
                _titleRenderer->stopAllActions();
                if (_unifySize)
                {
                    Action *zoomTitleAction = ScaleTo::create(ZOOM_ACTION_TIME_STEP, 1.0f, 1.0f);
                    _titleRenderer->runAction(zoomTitleAction);
                }
                else
                {
                    _titleRenderer->setScaleX(1.0f);
                    _titleRenderer->setScaleY(1.0f);
                }
            }
        }
    }
    else
    {
        _buttonNormalRenderer->stopAllActions();
        _buttonNormalRenderer->setScale(1.0);

        if (nullptr != _titleRenderer)
        {
            _titleRenderer->stopAllActions();
            _titleRenderer->setScaleX(1.0f);
            _titleRenderer->setScaleY(1.0f);
        }

    }
}

void Button::onPressStateChangedToPressed()
{
    _buttonNormalRenderer->setState(Scale9Sprite::State::NORMAL);

    if (_pressedTextureLoaded)
    {
        _buttonNormalRenderer->setVisible(false);
        _buttonClickedRenderer->setVisible(true);
        _buttonDisabledRenderer->setVisible(false);

        if (_pressedActionEnabled)
        {
            // 不操作子控件
            _buttonNormalRenderer->stopAllActions();
            _buttonClickedRenderer->stopAllActions();

            Action *zoomAction = ScaleTo::create(ZOOM_ACTION_TIME_STEP,
                                                 1.0f + _zoomScale,
                                                 1.0f + _zoomScale);
            _buttonClickedRenderer->runAction(zoomAction);

            _buttonNormalRenderer->setScale(1.0f + _zoomScale,
                                            1.0f + _zoomScale);

            if (nullptr != _titleRenderer)
            {
                _titleRenderer->stopAllActions();
                Action *zoomTitleAction = ScaleTo::create(ZOOM_ACTION_TIME_STEP,
                                                          1.0f + _zoomScale, 1.0f + _zoomScale);
                _titleRenderer->runAction(zoomTitleAction);
            }
        }
    }
    else
    {
        _buttonNormalRenderer->setVisible(true);
        _buttonClickedRenderer->setVisible(true);
        _buttonDisabledRenderer->setVisible(false);

        _buttonNormalRenderer->stopAllActions();
        _buttonNormalRenderer->setScale(1.0f +_zoomScale, 1.0f + _zoomScale);

        if (nullptr != _titleRenderer)
        {
            _titleRenderer->stopAllActions();
            _titleRenderer->setScaleX(1.0f + _zoomScale);
            _titleRenderer->setScaleY(1.0f + _zoomScale);
        }
    }
}

代码中,只对UIButton的4个子控件进行了操作,所以其他子控件并不会跟着缩放。

  • 之前有一些解决方案,是调用UIButton的getChildren()函数,遍历子节点,然后修改scale使其达到缩放的目的,但多数是写死了其放大后的比例,一但子控件本身有缩放就会出现问题,参考:子控件不跟着缩放

  • 即使通过一些方法记住子控件的原缩放比,若子控件比较靠近UIButton的边缘,仍然会发现子控件好像在浮动的现象,这是因为scale变了,子控件相对UIButton的position位置没有变导致的。

较完美的解决方案

  • 既然都是UIButton的子控件,为什么缩放时要缩放子控件呢?直接缩放UIButton本身不就可以了嘛。
  • 按照以上思路,1. 要记住UIButton的原比例;2. 不再操作子控件,直接操作UIButton。代码如下(origin拼写错误请各位忽略:joy: ):

/**
 * CCNode.h
 */
float _orignScale;              ///< origin scaling factor, just for UIButton
virtual void setOrignScale(float scale);
virtual float getOrignScale() const;

/**
 * CCNode.cpp
 * 增加orignScale
 */
// original scale getter
float Node::getOrignScale(void) const
{
    return _orignScale;
}

// original scale setter
void Node::setOrignScale(float scale)
{
    _orignScale = scale;
}

/**
 * UIButton.cpp
 */
void Button::onPressStateChangedToNormal()
{
    _buttonNormalRenderer->setVisible(true);
    _buttonClickedRenderer->setVisible(false);
    _buttonDisabledRenderer->setVisible(false);
    _buttonNormalRenderer->setState(Scale9Sprite::State::NORMAL);

    if (_pressedTextureLoaded)
    {
        if (_pressedActionEnabled)
        {
            // 不操作子控件
//            _buttonNormalRenderer->stopAllActions();
//            _buttonClickedRenderer->stopAllActions();

//            Action *zoomAction = ScaleTo::create(ZOOM_ACTION_TIME_STEP, _normalTextureScaleXInSize, _normalTextureScaleYInSize);
            //fixme: the zoomAction will run in the next frame which will cause the _buttonNormalRenderer to a wrong scale
//            _buttonNormalRenderer->setScale(1.0);
//            _buttonClickedRenderer->setScale(1.0);

//            if (nullptr != _titleRenderer)
//            {
//                _titleRenderer->stopAllActions();
//                if (_unifySize)
//                {
//                    Action *zoomTitleAction = ScaleTo::create(ZOOM_ACTION_TIME_STEP, 1.0f, 1.0f);
//                    _titleRenderer->runAction(zoomTitleAction);
//                }
//                else
//                {
//                    _titleRenderer->setScaleX(1.0f);
//                    _titleRenderer->setScaleY(1.0f);
//                }
//            }
            
            // 直接缩放UIButton控件
            this->stopAllActions();
            float orignScale = this->getOrignScale();
            float childScale = (orignScale == -1.0f ? this->getScale() : orignScale);
            this->setScale(childScale);
        }
    }
    else
    {
        _buttonNormalRenderer->stopAllActions();
        _buttonNormalRenderer->setScale(1.0);

        if (nullptr != _titleRenderer)
        {
            _titleRenderer->stopAllActions();
            _titleRenderer->setScaleX(1.0f);
            _titleRenderer->setScaleY(1.0f);
        }

    }
}

/**
 * UIButton.cpp
 */
void Button::onPressStateChangedToPressed()
{
    _buttonNormalRenderer->setState(Scale9Sprite::State::NORMAL);

    if (_pressedTextureLoaded)
    {
        _buttonNormalRenderer->setVisible(false);
        _buttonClickedRenderer->setVisible(true);
        _buttonDisabledRenderer->setVisible(false);

        if (_pressedActionEnabled)
        {
            // 不操作子控件
//            _buttonNormalRenderer->stopAllActions();
//            _buttonClickedRenderer->stopAllActions();
//
//            Action *zoomAction = ScaleTo::create(ZOOM_ACTION_TIME_STEP,
//                                                 1.0f + _zoomScale,
//                                                 1.0f + _zoomScale);
//            _buttonClickedRenderer->runAction(zoomAction);
//
//            _buttonNormalRenderer->setScale(1.0f + _zoomScale,
//                                            1.0f + _zoomScale);
//
//            if (nullptr != _titleRenderer)
//            {
//                _titleRenderer->stopAllActions();
//                Action *zoomTitleAction = ScaleTo::create(ZOOM_ACTION_TIME_STEP,
//                                                          1.0f + _zoomScale, 1.0f + _zoomScale);
//                _titleRenderer->runAction(zoomTitleAction);
//            }
            
            // 直接缩放UIButton控件
            this->stopAllActions();
            float orignScale = this->getOrignScale();
            float childScale = (orignScale == -1.0f ? this->getScale() : orignScale);
            this->setOrignScale(childScale);
            
            Action *zoomChildAction = ScaleTo::create(ZOOM_ACTION_TIME_STEP,
                                                      childScale * (1.0f + _zoomScale),
                                                      childScale * (1.0f + _zoomScale));
            this->runAction(zoomChildAction);
        }
    }
    else
    {
        _buttonNormalRenderer->setVisible(true);
        _buttonClickedRenderer->setVisible(true);
        _buttonDisabledRenderer->setVisible(false);

        _buttonNormalRenderer->stopAllActions();
        _buttonNormalRenderer->setScale(1.0f +_zoomScale, 1.0f + _zoomScale);

        if (nullptr != _titleRenderer)
        {
            _titleRenderer->stopAllActions();
            _titleRenderer->setScaleX(1.0f + _zoomScale);
            _titleRenderer->setScaleY(1.0f + _zoomScale);
        }
    }
}
  • 已知缺陷:
    1. 在执行点击事件之后,如果需要变更UIButton的scale缩放比,originScale需要手动置为初始值,否则,再次点击之后会重新设置为之前的缩放比。有啥好的想法一起交流一下~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值