iOS multiline edit box

Hi, I have been trying to mimic the multiline input text with cocos2d-x for a while, had previously a version of CCTextFieldTTF with multiline support, but problem is, we don’t have the cursor here, or can’t benefit of the keyboard suggestions, I guess that why in general is better to use CCEditBox, but CCEditBox doesn’t support multiline text either.

So I finally created my own using a UIKit UITextView element. Attached is the code in case anyone interested (I wish I had this code few months ago!).

CCSize size = CCDirector::sharedDirector()->getWinSize();
CCSize textViewSize = CCSize(size.width-40,  size.height/3);
MyTextView* textView = MyTextView::createWithRect(CCRect(20, size.height - textViewSize.height, textViewSize.width, textViewSize.height), "Type your message", ccc3(0,0,0,255), container);
textView->setDelegate(this);

To use just need to include the delegate methods, in particular the textViewKeyboardWillShow will give you the keyboard size so you can scroll your scene up so it doesn’t get obscured by the keyboard. Something like:

void MyClass::textViewKeyboardWillShow(CCSize size)
{
    if (isInputText || !textView->isVisible()) return;
    
    CCLOG("Keyboard heigh: %f", size.height);
    
    CCSize contentSize = textView->getContentSize();
    CCRect rect = CCRectMake(0, 0, contentSize.width, contentSize.height);
    CCRect rectTracked = CCRectApplyAffineTransform(rect, textView->nodeToWorldTransform());
    CCLog("++++++ %f, %f, %f, %f", rectTracked.origin.x, rectTracked.origin.y, rectTracked.size.width, rectTracked.size.height);
    // some adjustment for margin between the keyboard and the edit box.
    rectTracked.origin.y -= 4;
    
    // if the keyboard area doesn't intersect with the tracking node area, nothing needs to be done.
    if (!rectTracked.intersectsRect(CCRect(0, 0, size.width, size.height)))
    {
        CCLOG("needn't to adjust view layout.");
        return;
    }
     
    // assume keyboard at the bottom of screen, calculate the vertical adjustment.
    adjustHeight = size.height - rectTracked.getMinY();
    
    this->stopAllActions();
    this->runAction(CCMoveTo::create(0.2, ccp(0, adjustHeight)));
}

Then on close:

void MyClass::textViewKeyboardWillHide()
{
    this->stopAllActions();
    this->runAction(CCMoveTo::create(0.2, ccp(0, 0)));
}

Few notes and limitations:

  • textView is the instance of the class.
  • font size and face are defined with two external constants, FONT_NAME_REGULAR and FONT_SIZE_INPUT_SMALL, this would be better added to the constructor.
  • It’s only done for iOS.
  • We cannot have more than one instance at the same time.
  • If you use CCEditBox in combination, use the flag isInputText to prevent this method to scroll twice your screen (CCEditBox already manages the screen scroll itself)

I’m pretty sure this can be hugely improved, but so far works ok to me and my clients are now happy the apps behave more similar to any other iOS app.

MyTextView.zip (4.4 KB)