Tuesday, October 18, 2011

Custom text entry in AIR for iOS

On Android, you can create your own text entry controls using the InteractiveObject class and the needsSoftKeyboard and requestSoftKeyBoard() APIs. This doesn't work on iOS for various reasons. However, with some recent changes to the runtime, it is now possible to fake it.

Instead of using an InteractiveObject, you use an off screen TextField object to control the soft keyboard and to get the text as it is typed.

Code below the break...

This example creates two wonderfully colored rectangles on the screen. Touch the top one to open the keyboard; touch the bottom to close it. All the interesting action is in trace statements, so you have to hook it up to the debugger. (I only tested this on iOS, if you try elsewhere and it doesn't work, let me know.

package
{
    import flash.desktop.NativeApplication;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.events.SoftKeyboardEvent;
    import flash.events.TextEvent;
    import flash.text.TextField;
    import flash.text.TextFieldType;
    import flash.text.TextFormat;
    import flash.ui.Keyboard;
   
    public class iOSTextField extends Sprite
    {
        private var tf:TextField;
        private var show:Sprite;
        private var hide:Sprite;
        public function iOSTextField()
        {
            super();
            trace("init");
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            tf = new TextField();
            tf.height = 0;
            tf.width = 0;
            tf.x = 50;
            tf.y = -150;
            tf.setTextFormat( new TextFormat( "_sans", 90 ) );
            tf.type = TextFieldType.INPUT;
            tf.visible = false;
            tf.addEventListener( Event.CHANGE, onTFChange );
            tf.addEventListener( SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE, softKeyboardEvent );
            tf.addEventListener( SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, softKeyboardEvent );
           
            this.addChild( tf );
               
           
            show = new Sprite();
            show.graphics.beginFill( 0xff880000 );
            show.graphics.drawRect(0, 0, 400, 100);
            show.x = 50;
            show.y = 50;
            this.addChild( show );
            show.addEventListener( MouseEvent.MOUSE_DOWN, showKeyboard );

            hide = new Sprite();
            hide.graphics.beginFill( 0xffff00ff );
            hide.graphics.drawRect(0, 0, 400, 100);
            hide.x = 50;
            hide.y = 180;
            this.addChild( hide );
            hide.addEventListener( MouseEvent.MOUSE_DOWN, hideKeyboard );
           
           
        }
       
        private function showKeyboard( event:Event ):void
        {
            trace("show");
            tf.requestSoftKeyboard();
        }
        private function hideKeyboard( event:Event ):void
        {
            trace("hide");
            this.stage.focus = null;
        }
        private function onTFChange( event:Event ):void
        {
            trace("Character typed: " + tf.text.charAt( tf.text.length - 1 ) );
            tf.text = "";
        }   
        private function softKeyboardEvent( event:SoftKeyboardEvent ):void
        {
            trace( this.stage.softKeyboardRect );
        }
    }
}

I tried the same technique using StageText in AIR 3, but it didn't work. There's a bug that just closes the soft keyboard immediately after opening it. This bug is supposed to be fixed in AIR 3.1. If you can't wait that long try opening the keyboard from a non-mouse event (the bug notes are a bit vague on this point, but the problem might have to do specifically with mouse events -- no promises, though, and I haven't tried it.)

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.