CCTextFieldTTF issue - keyboard not shown

Hi,

I’ve got a text field on screen which on iOS opens a keyboard.
Text field is within a popup, so in onTextFieldAttachWithIME I move it up a bit and in onTextFieldDetachWithIME I move it down.
When running on iOS everything seems fine, however when I run it on Android device keyboard does not show up.
Popup moves a bit to the top, but keyboard is not there.

What could be wrong?

I’ve basically copied and pasted code of the cctextfieldttf test and used the default text field [+added delegate to support the methods mentioned above].

Any help will be appreciated.

Thanks,
Krystian

Here’s the code for my input box:

    // TEXT INPUT

    //////////////////////////////////////////////////////////////////////////
    // implement KeyboardNotificationLayer
    //////////////////////////////////////////////////////////////////////////

    KeyboardNotificationLayer::KeyboardNotificationLayer()
    : m_pTrackNode(0) {
        setIsTouchEnabled(true);
    }

    void KeyboardNotificationLayer::registerWithTouchDispatcher() {
        CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, 0, false);
    }

    void KeyboardNotificationLayer::keyboardWillShow(CCIMEKeyboardNotificationInfo& info) {
        CCLOG("TextInputTest:keyboardWillShowAt(origin:%f,%f, size:%f,%f)",
        info.end.origin.x, info.end.origin.y, info.end.size.width, info.end.size.height);

        if (!m_pTrackNode) {
            return;
        }

        CCRect rectTracked = getRect(m_pTrackNode);
        CCLOG("TextInputTest:trackingNodeAt(origin:%f,%f, size:%f,%f)",
        rectTracked.origin.x, rectTracked.origin.y, rectTracked.size.width, rectTracked.size.height);

        // if the keyboard area doesn't intersect with the tracking node area, nothing need to do.
        if (!CCRect::CCRectIntersectsRect(rectTracked, info.end)) {
            return;
        }

        // assume keyboard at the bottom of screen, calculate the vertical adjustment.
        float adjustVert = CCRect::CCRectGetMaxY(info.end) - CCRect::CCRectGetMinY(rectTracked);
        CCLOG("TextInputTest:needAdjustVerticalPosition(%f)", adjustVert);

        // move all the children node of KeyboardNotificationLayer
        CCArray *children = getChildren();
        CCNode *node = 0;
        int count = children->count();
        CCPoint pos;
        for (int i = 0; i < count; ++i) {
            node = (CCNode *) children->objectAtIndex(i);
            pos = node->getPosition();
            pos.y += adjustVert;
            node->setPosition(pos);
        }
    }


    // CCLayer function

    bool KeyboardNotificationLayer::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) {
        CCLOG("++++++++++++++++++++++++++++++++++++++++++++");
        m_beginPos = pTouch->locationInView(pTouch->view());
        m_beginPos = CCDirector::sharedDirector()->convertToGL(m_beginPos);
        return true;
    }

    void KeyboardNotificationLayer::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) {
        if (!m_pTrackNode) {
            return;
        }

        CCPoint endPos = pTouch->locationInView(pTouch->view());
        endPos = CCDirector::sharedDirector()->convertToGL(endPos);

        float delta = 5.0f;
        if (::abs(endPos.x - m_beginPos.x) > delta
                || ::abs(endPos.y - m_beginPos.y) > delta) {
            // not click
            m_beginPos.x = m_beginPos.y = -1;
            return;
        }

        // decide the trackNode is clicked.
        CCRect rect;
        CCPoint point = convertTouchToNodeSpaceAR(pTouch);
        CCLOG("KeyboardNotificationLayer:clickedAt(%f,%f)", point.x, point.y);

        rect = getRect(m_pTrackNode);
        CCLOG("KeyboardNotificationLayer:TrackNode at(origin:%f,%f, size:%f,%f)",
        rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);

        this->onClickTrackNode(CCRect::CCRectContainsPoint(rect, point));
        CCLOG("----------------------------------");
    }

    //////////////////////////////////////////////////////////////////////////
    // implement TextFieldTTFDefaultTest
    //////////////////////////////////////////////////////////////////////////

    std::string TextFieldTTFDefaultTest::subtitle() {
        return "TextFieldTTF with default behavior test";
    }

    void TextFieldTTFDefaultTest::onClickTrackNode(bool bClicked) {
        CCTextFieldTTF *pTextField = (CCTextFieldTTF *) m_pTrackNode;
        if (bClicked) {
            // TextFieldTTFTest be clicked
            CCLOG("TextFieldTTFDefaultTest:CCTextFieldTTF attachWithIME");
            pTextField->attachWithIME();
        }
        else {
            // TextFieldTTFTest not be clicked
            CCLOG("TextFieldTTFDefaultTest:CCTextFieldTTF detachWithIME");
            pTextField->detachWithIME();
        }
    }

    void TextFieldTTFDefaultTest::onEnter() {
        KeyboardNotificationLayer::onEnter();

        // add CCTextFieldTTF
        CCSize s = CCDirector::sharedDirector()->getWinSize();

        CCTextFieldTTF *pTextField = CCTextFieldTTF::textFieldWithPlaceHolder("",
                FONT_NAME,
                FONT_SIZE);
        pTextField->setPosition(ogsPosition(ccp(0, -30), ogsAnchorCenter));
        addChild(pTextField);

        pTextField->setDelegate(this);

        m_pTrackNode = pTextField;
    }

    std::string TextFieldTTFDefaultTest::getString() {
        return ((CCTextFieldTTF*) m_pTrackNode)->getString();
    }

    bool TextFieldTTFDefaultTest::onTextFieldAttachWithIME (CCTextFieldTTF *sender) {
        this->getParent()->setPosition(ccpAdd(this->getParent()->getPosition(), ogsPosition(ccp(0, 100), ogsAnchorBottomLeft)));
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
        //on ios field will move itself, so we have to compensate
        this->setPosition(ogsPosition(ccp(0, -50), ogsAnchorBottomLeft));
#endif
        return false;
    }
    bool TextFieldTTFDefaultTest::onTextFieldDetachWithIME (CCTextFieldTTF *sender) {
        this->getParent()->setPosition(ccpAdd(this->getParent()->getPosition(), ogsPosition(ccp(0, -100), ogsAnchorBottomLeft)));
        return false;
    }

    bool TextFieldTTFDefaultTest::onTextFieldInsertText(CCTextFieldTTF * pSender, const char * text, int nLen) {
        // if insert enter, treat as default to detach with ime
        if ('\n' == *text) {
            return false;
        }

        // if the textfield's char count more than m_nCharLimit, doesn't insert text anymore.
        if (pSender->getCharCount() >= m_nCharLimit) {
            return true;
        }

        return false;
    }

and header:

    //////////////////////////////////////////////////////////////////////////
    // KeyboardNotificationLayer for test IME keyboard notification.
    //////////////////////////////////////////////////////////////////////////

    class KeyboardNotificationLayer : public CCLayer, public CCIMEDelegate
    {
    public:
        KeyboardNotificationLayer();
        virtual std::string subtitle() = 0;
        virtual void onClickTrackNode(bool bClicked) = 0;

        virtual void registerWithTouchDispatcher();
        virtual void keyboardWillShow(CCIMEKeyboardNotificationInfo& info);

        // CCLayer
        virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
        virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);

    protected:
        CCNode * m_pTrackNode;
        CCPoint  m_beginPos;
    };

    //////////////////////////////////////////////////////////////////////////
    // TextFieldTTFDefaultTest for test TextFieldTTF default behavior.
    //////////////////////////////////////////////////////////////////////////

    class TextFieldTTFDefaultTest : public KeyboardNotificationLayer, public CCTextFieldDelegate
    {
    public:
        int m_nCharLimit;
        std::string getString();
        // KeyboardNotificationLayer
        virtual std::string subtitle();
        virtual void onClickTrackNode(bool bClicked);
        virtual bool onTextFieldAttachWithIME (CCTextFieldTTF *sender);
        virtual bool onTextFieldDetachWithIME (CCTextFieldTTF *sender);
        virtual bool onTextFieldInsertText(CCTextFieldTTF * pSender, const char * text, int nLen);

        // CCLayer
        virtual void onEnter();
    };

Anything? please?
At least a hint at where to start with this?

The only thing I get in logcat when clicking on field is:

02-02 10:57:21.972: DEBUG/dalvikvm(223): GC freed 4112 objects / 677168 bytes in 55ms

EDIT:

nope, there’s more:

02-02 11:03:33.132: DEBUG/dalvikvm(223): +++ not scanning '/system/lib/libwebcore.so' for 'nativeTouchesMove' (wrong CL)
02-02 11:03:33.132: DEBUG/dalvikvm(223): +++ not scanning '/system/lib/libexif.so' for 'nativeTouchesMove' (wrong CL)
02-02 11:03:33.132: DEBUG/dalvikvm(223): +++ not scanning '/system/lib/libmedia_jni.so' for 'nativeTouchesMove' (wrong CL)
02-02 11:03:33.162: DEBUG/cocos2d-x debug info(223): 0.000000.1    0.000000.1    0.833333.1    0.750000.1    0.000000.1    100.000000.1

I’ve renamed all CCLOG to CCLog and here’s what I get in logcat:
[this is what I get when I click on the text field, expecting the keyboard to show up]

02-02 13:58:16.855: DEBUG/cocos2d-x debug info(11566): ++++++++++++++++++++++++++++++++++++++++++++
02-02 13:58:16.905: INFO/InputDispatcher(2787): Delivering touch to current input target: action: 1, channel '40c77338 [my class] (server)'
02-02 13:58:16.925: DEBUG/cocos2d-x debug info(11566): KeyboardNotificationLayer:clickedAt(433.000000,220.000000)
02-02 13:58:16.925: DEBUG/cocos2d-x debug info(11566): KeyboardNotificationLayer:TrackNode at(origin:286.000000,203.500000, size:228.000000,28.000000)
02-02 13:58:16.925: DEBUG/cocos2d-x debug info(11566): TextFieldTTFDefaultTest:CCTextFieldTTF attachWithIME
02-02 13:58:16.925: DEBUG/cocos2d-x debug info(11566): ----------------------------------

and here’s what I get when I click one more time, now somewhere else than the text field:

02-02 13:58:23.380: DEBUG/cocos2d-x debug info(11566): ++++++++++++++++++++++++++++++++++++++++++++
02-02 13:58:23.445: INFO/InputDispatcher(2787): Delivering touch to current input target: action: 1, channel '40c77338 [my class] (server)'
02-02 13:58:23.460: DEBUG/cocos2d-x debug info(11566): KeyboardNotificationLayer:clickedAt(656.000000,93.000000)
02-02 13:58:23.460: DEBUG/cocos2d-x debug info(11566): KeyboardNotificationLayer:TrackNode at(origin:286.000000,203.500000, size:228.000000,28.000000)
02-02 13:58:23.460: DEBUG/cocos2d-x debug info(11566): TextFieldTTFDefaultTest:CCTextFieldTTF detachWithIME
02-02 13:58:23.460: DEBUG/cocos2d-x debug info(11566): ----------------------------------

Another Edit:

I’ve copied and pasted code from Android tests.
I’ve got exactly the same code for TextFieldTTFDefaultTest, KeyboardNotificationLayer & TextFieldTTFActionTest.

Here’s how I add them to the layer:

KeyboardNotificationLayer *pTestLayer = new TextFieldTTFActionTest();
            pTestLayer->autorelease();
            m_pNotificationLayer = pTestLayer;
            addChild(pTestLayer);

And still when I tap on the text field keyboard will not show up :frowning:
I’m lost a bit :confused:
I’m not sure what’s missing :confused:

I’ve been able to find something new.
In Cocos2dxGLSurfaceView there’s the initView() method and inside new Handler is created.
In there, when I get to the handleMessage method the mTextField field is null.
This causes the keyboard not to open.

Now I’ll have to find why… but any help will be appreciated

EDIT:
Got it…
The problem is with Lua projects.
Normally, in the project generated class, which extends Cocos2dxActivity you have:

protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);

        // get the packageName,it's used to set the resource path
        String packageName = getApplication().getPackageName();
        super.setPackageName(packageName);

        setContentView(R.layout.test_demo);
        mGLView = (Cocos2dxGLSurfaceView) findViewById(R.id.test_demo_gl_surfaceview);
        mGLView.setTextField((EditText)findViewById(R.id.textField));
    }

but in Lua projects it’s:

 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // pass context to device id
        DeviceInfo devInfo = DeviceInfo.getInstance();
        devInfo.setContext(this);
        System.out.println("cocos" + DeviceInfo.getDeviceId());

        // get the packageName,it's used to set the resource path
        String packageName = getApplication().getPackageName();
        super.setPackageName(packageName);

        mGLView = new LuaGLSurfaceView(this);
        setContentView(mGLView);
    }

So the text field is not set…

Finally solved it:
http://www.cocos2d-x.org/boards/11/topics/7865?r=7869