I’ve been stumbling on this issue as well. The problem is that UITextField is not part of the OpenGL View, and globally not part of the whole CCnode hierarchy. The easiest solution out of it would be to change this method :
void CCEditBoxImplIOS::setPosition(const CCPoint& pos)
//TODO should consider anchor point, the default value is (0.5, 0,5)
[GET_IMPL setPosition:convertDesignCoordToScreenCoord(ccp(pos.x-m_tContentSize.width/2, pos.y+m_tContentSize.height/2), m_bInRetinaMode)];
Here, you should not use pos but rather take a look at the whole hierarchy to resolve its real position before passing it to convertDesignCoordToScreenCoord.
To get the real position, I did a similar algorithm (to save you the trouble), which is about :
CCPoint realPosition = obj->getPosition();
CCNode* parent = getParent(obj);
while(parent != NULL)
realPosition.x = realPosition.x * parent->getScaleX() + parent->getPosition().x;
realPosition.y = realPosition.y * parent->getScaleY() + parent->getPosition().y;
parent = getParent(parent);
//here, you get the real position to assign to m_pEditBoxImpl
The only problem point is to implement the getParent method, which should return NULL if there is no parent. That would be easy to get from a CCNode, but how do you pass that CCNode to the CCEditBoxImpl in a clean way ? Or should that calculation be done by the CCEditBox for iOS only ?
As for the problem of UITextField being always on top, it’s not an easily solved problem. When you using any other UIView, it will be either on top or under OpenGL View. There can not be any UIView in “the middle” of an OpenGL View. Some hack around it would be :
- replace by a cocos label when you are not editing so that the label is in the cocos hierarchy for that time. It obviously involve quite a bit of fiddling to look good all the time and may not always fit in your context.
- put the items you want on top of the UITextField on another UIView, not on OpenGL View (I don’t think it’s possible to have 2 separate OpenGL View) : you loose all cocos capabilities on those items, but it’ll be on top. It’s an easy solution if you just have a simple overlay for example.
As an aside, I spotted another problem with CCEditBox implementation on iOS (I didn’t try yet on Android) : there is a problem with the view moving in portrait mode : to be precise, if the CCEditBox is on the right part of the screen, the view will move properly, but if it’s on the left, the view won’t move (everything else working fine). I suspect the hit collision, at some point, is done only for landscape. I’ll try to get to the bottom of it.
Edit : this problem is actually caused by the very problem of that thread, and not portrait. I did a custom hack in my code to go around the problem, but the same issue has another side effect : in this method, the rect is not properly calibrated either, resulting to a miss :
void CCEditBox::keyboardWillShow(CCIMEKeyboardNotificationInfo& info)
CCRect rectTracked = getRect(this);
// if the keyboard area doesn't intersect with the tracking node area, nothing needs to be done.
CCLOG("needn't to adjust view layout.");
The issue comes from the getRect method which only look for current node position, instead of taking into account the hierarchy. The size should take into account scale and parents scale as well.