为什么子控件不跟着缩放
- 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拼写错误请各位忽略
):
/**
* 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);
}
}
}
- 已知缺陷:
- 在执行点击事件之后,如果需要变更UIButton的scale缩放比,originScale需要手动置为初始值,否则,再次点击之后会重新设置为之前的缩放比。有啥好的想法一起交流一下~