14 Replies Latest reply on Aug 8, 2013 6:24 AM by PablitoLamb

    keyboard won't go up on TextInput focus flex 4.6-iOS

    mikmiki Level 1

      hi,

      i'm using the TextInput with a custom skin i've made.

      after upgrading to flex 4.6 no keyboard event is triggered when focousing on the TextInput.

      i've noticed some messages on the forum about the issue with no workaround\solution. anyone?

        • 1. Re: keyboard won't go up on TextInput focus flex 4.6-iOS
          Level 1

          When I said that (and you can see in the forum), no ones believe me

           

          New new stage text it's so buggy between devices that now we dont have anymore "code once, runs everywhere".

           

          In iOS (v5), only using the new stage Flex skin without costumization will work (the keyboard won't go up in other situations)

          In PlayBook (v1.0.8), only using the old Flex skin will work (push a view, input in a text input, pop a view and push a view again, you will have an exception with the new stage text)

          In Android both new stage text and old text skin will work (with the new stage text you will see some strange behaviours but works)

           

          With Flex 4.5.1 you dont have to worry about this (the Flex mobile now seems more html that you have to test in several devices and put code to workaround)

          • 2. Re: keyboard won't go up on TextInput focus flex 4.6-iOS
            mikmiki Level 1

            so there is no workaround?! no samples for skins for TextInput that will work on iOS?

            • 3. Re: keyboard won't go up on TextInput focus flex 4.6-iOS
              Level 1

              My case:

               

              Before Flex 4.6 I have a costum TextInput and TextArea and other class that extends from my TextInput with skin costumization and code in the click event and works very well in the 3 platforms without have to test in all and I only have a Android device (I dont need the new features from stage text).

               

              After Flex 4.6 I have a lot of users complain about the app in iOS and recently in PlayBook

               

              Now I have a lot of code and repeatedly TextInput and TextArea class extended (without skin costumization) to work with iOS, PlayBook and Android (it's a very annoying)

               

              Other think: Applying the spark skin in the TextInput and TextArea you will lose and rounded corners, so good bye to same layout between devices.

               

              The Flex 4.6 brings new important components and a little better performance so I cant go back to Flex 4.5.1 and I hope I dont have more surprises in the future because since I have to use stage text in the iOS I have now dependent of the system behaviour (in the future could be a problem)

              • 4. Re: keyboard won't go up on TextInput focus flex 4.6-iOS
                drkstr_1 Level 4

                I rolled back to the 4.5.1 TextInput skin myself. Stage text caused to many problems for me, and I had no need for the features it provides. No more issues since...

                 

                 

                ////////////////////////////////////////////////////////////////////////////////
                //
                //  ADOBE SYSTEMS INCORPORATED
                //  Copyright 2010 Adobe Systems Incorporated
                //  All Rights Reserved.
                //
                //  NOTICE: Adobe permits you to use, modify, and distribute this file
                //  in accordance with the terms of the license agreement accompanying it.
                //
                ////////////////////////////////////////////////////////////////////////////////
                
                
                package spark.skins.mobile 
                {
                import flash.events.Event;
                import flash.events.SoftKeyboardEvent;
                import flash.system.Capabilities;
                
                
                import mx.core.DPIClassification;
                import mx.core.EventPriority;
                import mx.core.mx_internal;
                
                
                import spark.components.TextInput;
                import spark.components.supportClasses.StyleableTextField;
                import spark.skins.mobile.supportClasses.TextSkinBase;
                import spark.skins.mobile160.assets.TextInput_border;
                import spark.skins.mobile240.assets.TextInput_border;
                import spark.skins.mobile320.assets.TextInput_border;
                
                
                use namespace mx_internal;
                
                
                /**
                 *  ActionScript-based skin for TextInput controls in mobile applications. 
                 * 
                 * @see spark.components.TextInput
                 * 
                 *  @langversion 3.0
                 *  @playerversion Flash 10
                 *  @playerversion AIR 2.5 
                 *  @productversion Flex 4.5
                 */
                public class TextInputSkin extends TextSkinBase 
                {
                    //--------------------------------------------------------------------------
                    //
                    //  Constructor
                    //
                    //--------------------------------------------------------------------------
                    
                    /**
                     *  Constructor.
                     *  
                     *  @langversion 3.0
                     *  @playerversion Flash 10
                     *  @playerversion AIR 2.5
                     *  @productversion Flex 4.5
                     */
                    public function TextInputSkin()
                    {
                        super();
                        
                        // on iOS, make adjustments for native text rendering
                        _isIOS = (Capabilities.version.indexOf("IOS") == 0);
                        
                        switch (applicationDPI)
                        {
                            case DPIClassification.DPI_320:
                            {
                                borderClass = spark.skins.mobile320.assets.TextInput_border;
                                layoutCornerEllipseSize = 24;
                                measuredDefaultWidth = 600;
                                measuredDefaultHeight = 66;
                                layoutBorderSize = 2;
                                
                                break;
                            }
                            case DPIClassification.DPI_240:
                            {
                                borderClass = spark.skins.mobile240.assets.TextInput_border;
                                layoutCornerEllipseSize = 12;
                                measuredDefaultWidth = 440;
                                measuredDefaultHeight = 50;
                                layoutBorderSize = 1;
                                
                                break;
                            }
                            default:
                            {
                                borderClass = spark.skins.mobile160.assets.TextInput_border;
                                layoutCornerEllipseSize = 12;
                                measuredDefaultWidth = 300;
                                measuredDefaultHeight = 33;
                                layoutBorderSize = 1;
                                
                                break;
                            }
                        }
                    }
                    
                    //--------------------------------------------------------------------------
                    //
                    //  Variables
                    //
                    //--------------------------------------------------------------------------
                    
                    /** 
                     *  @copy spark.skins.spark.ApplicationSkin#hostComponent
                     */
                    public var hostComponent:TextInput;  // SkinnableComponent will populate
                    
                    /**
                     *  @private
                     */
                    private var _isIOS:Boolean;
                    
                    /**
                     *  @private
                     */
                    private var _isEditing:Boolean;
                    
                    /**
                     *  @private
                     */
                    override protected function createChildren():void
                    {
                        super.createChildren();
                        
                        textDisplay.addEventListener("editableChanged", editableChangedHandler);
                        
                        // remove hit area improvements on iOS when editing
                        if (_isIOS)
                        {
                            textDisplay.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATING, textDisplay_softKeyboardActivatingHandler, false, EventPriority.DEFAULT_HANDLER);
                            textDisplay.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, textDisplay_softKeyboardDeactivateHandler);
                        }
                    }
                    
                    /**
                     *  @private
                     */
                    override protected function measure():void
                    {
                        super.measure();
                        
                        var paddingLeft:Number = getStyle("paddingLeft");
                        var paddingRight:Number = getStyle("paddingRight");
                        var paddingTop:Number = getStyle("paddingTop");
                        var paddingBottom:Number = getStyle("paddingBottom");
                        var textHeight:Number = getStyle("fontSize") as Number;
                        
                        if (textDisplay)
                        {
                            // temporarily change text for measurement
                            var oldText:String = textDisplay.text;
                            
                            // commit styles so we can get a valid textHeight
                            textDisplay.text = "Wj";
                            textDisplay.commitStyles();
                            
                            textHeight = textDisplay.measuredTextSize.y;
                            textDisplay.text = oldText;
                        }
                        
                        // width is based on maxChars (if set)
                        if (hostComponent && hostComponent.maxChars)
                        {
                            // Grab the fontSize and subtract 2 as the pixel value for each character.
                            // This is just an approximation, but it appears to be a reasonable one
                            // for most input and most font.
                            var characterWidth:int = Math.max(1, (getStyle("fontSize") - 2));
                            measuredWidth =  (characterWidth * hostComponent.maxChars) + 
                                paddingLeft + paddingRight + StyleableTextField.TEXT_WIDTH_PADDING;
                        }
                        
                        measuredHeight = paddingTop + textHeight + paddingBottom;
                    }
                    
                    /**
                     *  @private
                     */
                    override protected function layoutContents(unscaledWidth:Number, 
                                                               unscaledHeight:Number):void
                    {
                        super.layoutContents(unscaledWidth, unscaledHeight);
                        
                        // position & size border
                        if (border)
                        {
                            setElementSize(border, unscaledWidth, unscaledHeight);
                            setElementPosition(border, 0, 0);
                        }
                        
                        // position & size the text
                        var paddingLeft:Number = getStyle("paddingLeft");
                        var paddingRight:Number = getStyle("paddingRight");
                        var paddingTop:Number = getStyle("paddingTop");
                        var paddingBottom:Number = getStyle("paddingBottom");
                        
                        var unscaledTextWidth:Number = unscaledWidth - paddingLeft - paddingRight;
                        var unscaledTextHeight:Number = unscaledHeight - paddingTop - paddingBottom;
                        
                        // default vertical positioning is centered
                        var textHeight:Number = getElementPreferredHeight(textDisplay);
                        var textY:Number = Math.round(0.5 * (unscaledTextHeight - textHeight)) + paddingTop;
                        
                        // On iOS the TextField top and bottom edges are bounded by the padding.
                        // On all other platforms, the height of the textDisplay is
                        // textHeight + paddingBottom to increase hitArea on bottom.
                        // Note: We don't move the Y position upwards because TextField
                        // has way to set vertical positioning.
                        // Note: iOS is a special case due to the clear button provided by the
                        // native text control used while editing.
                        var adjustedTextHeight:Number = (_isIOS && _isEditing) ? textHeight : textHeight + paddingBottom;
                
                
                        if (textDisplay)
                        {
                            // We're going to do a few tricks to try to increase the size of our hitArea to make it 
                            // easier for users to select text or put the caret in a certain spot.  To do that, 
                            // rather than set textDisplay.x=paddingLeft,  we are going to set 
                            // textDisplay.leftMargin = paddingLeft.  In addition, we're going to size the height 
                            // of the textDisplay larger than just the size of the text inside to increase the hitArea
                            // on the bottom.  We'll also assign textDisplay.rightMargin = paddingRight to increase the 
                            // the hitArea on the right.  Unfortunately, there's no way to increase the hitArea on the top
                            // just yet, but these three tricks definitely help out with regards to user experience.  
                            // See http://bugs.adobe.com/jira/browse/SDK-29406 and http://bugs.adobe.com/jira/browse/SDK-29405
                            
                            // set leftMargin, rightMargin to increase the hitArea.  Need to set it before calling commitStyles().
                            var marginChanged:Boolean = ((textDisplay.leftMargin != paddingLeft) || 
                                (textDisplay.rightMargin != paddingRight));
                            
                            textDisplay.leftMargin = paddingLeft;
                            textDisplay.rightMargin = paddingRight;
                            
                            // need to force a styleChanged() after setting leftMargin, rightMargin if they 
                            // changed values.  Then we can validate the styles through commitStyles()
                            if (marginChanged)
                                textDisplay.styleChanged(null);
                            textDisplay.commitStyles();
                            
                            setElementSize(textDisplay, unscaledWidth, adjustedTextHeight);
                            
                            // set x=0 since we're using textDisplay.leftMargin = paddingLeft
                            setElementPosition(textDisplay, 0, textY);
                        }
                        
                        if (promptDisplay)
                        {
                            promptDisplay.commitStyles();
                            setElementSize(promptDisplay, unscaledTextWidth, adjustedTextHeight);
                            setElementPosition(promptDisplay, paddingLeft, textY);
                        }
                    }
                    
                    /**
                     *  @private
                     */
                    private function editableChangedHandler(event:Event):void
                    {
                        invalidateDisplayList();
                    }
                    
                    /**
                     *  @private
                     */
                    private function textDisplay_softKeyboardActivatingHandler(event:SoftKeyboardEvent):void
                    {
                        if (event.isDefaultPrevented())
                            return;
                        
                        _isEditing = true;
                        invalidateDisplayList();
                    }
                    
                    /**
                     *  @private
                     */
                    private function textDisplay_softKeyboardDeactivateHandler(event:SoftKeyboardEvent):void
                    {
                        _isEditing = false;
                        invalidateDisplayList();
                    }
                }
                }
                
                
                • 5. Re: keyboard won't go up on TextInput focus flex 4.6-iOS
                  Level 1

                  For Android I have a device.

                  For PlayBook the emulator seems to be very trusty because its the same OS in a virtual machine.

                  For the iOS I will buy one iPad as soon as the new model be released and then I will do the same as you but I must test in the device to be sure all works.

                   

                  The new stage text its very very buggy and have dependency to the device and the apply of text input spark skin its ugly and also dont work in all devices so drskstr_1 the way you solve the problem its the best solution no dought

                   

                  Update: drskstr_1 thank you very much for your contribution.

                  • 6. Re: keyboard won't go up on TextInput focus flex 4.6-iOS
                    Level 1

                    I just copy the entire code of the TextInputSkin and TextAreaSkin for the mobile (and all dependency base class) from the Flex 4.5.1 and works perflectly again in my Android device (with the rounded corner, events, perfect drawing, ...). Also tested in the PlayBook simulator with also great results. Only can't test in iOS device for now.

                     

                    With this, I have now all the good features from the Flex 4.6 with the stability between devices from the Flex 4.5.1

                    • 7. Re: keyboard won't go up on TextInput focus flex 4.6-iOS
                      drkstr_1 Level 4

                      All good in iOS from my end.

                       

                      (tested on iPad 1 and 2)

                      • 9. Re: keyboard won't go up on TextInput focus flex 4.6-iOS
                        TVonthemob Level 1

                        How exactly did you implement this? I have a basic application(not a view based or tabbed base) where I lose the keyboard on a ios devices.  Should I put this text in the main mxml ? Or should i attach some older .swc for the 4.5.1 sdk?

                        if I could keep the option for softKeyboardType="contact" or whatever that would be great, but obviously having a keyboard is most important.

                         

                        thanks for help with the work around.

                        Anthony

                        • 10. Re: keyboard won't go up on TextInput focus flex 4.6-iOS
                          Level 1

                          My original full tutorial

                           

                          What I did was:

                          1. Download again the Flex 4.5.1 (http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+4.5)
                          2. Search in the Flex source code for the class TextInputSkin and TextAreaSkin from the mobile skin folder (attention here not to use the wrong skin, ie from non mobile)
                          3. Copy this 2 files to your project (or you lib if you have one costumized as I have)
                          4. Fix the necessary thinks (package name, etc ...)
                          5. Create a costumized TextInput and TextArea (if you're not already a) and extend from the TextInput and TextArea from Flex 4.6
                          6. In the constrution of your costumized class, just put: super.setStyle("skinClass", MyCopyOfTextInputSkin) in the TextInput costumized class and super.setStyle("skinClass", MyCopyOfTextAreaSkin) in the TextArea costumized class
                          7. Use this new class (if it were already using) instead of the native TextInput and TextArea from the Flex 4.6 and build
                          8. You will get some errors, so check them in your TextInputSkin and TextAreaSkin copies and check what is missing (just copy the other files of errors to the same folder) and fix the namespace until you dont have any more errors

                           

                          Then I test in a real Android device and in the PlayBook simulator (can't test for now in a iOS device) and all the problems from the TextInput and TextArea from the Flex 4.6 disappeared and kept the graphic aspect of the rounded boxes from the Flex 4.5.1.

                          • 11. Re: keyboard won't go up on TextInput focus flex 4.6-iOS
                            mikmiki Level 1

                            i'm not trying the above. i'm trying to add a custom text input skin as below.

                            i have tried to also copy paste textinput and textinputskin from 4.5 to 4.6 with no success.

                             

                             

                            <?xml version="1.0" encoding="utf-8"?>

                            <!-- sparktextcontrols\mySkins\CustomTextInputSkin.mxml -->

                            <s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009"

                                xmlns:s="library://ns.adobe.com/flex/spark"

                                xmlns:fb="http://ns.adobe.com/flashbuilder/2009"

                                alpha.disabledStates="0.5" blendMode="normal">

                             

                            <fx:Metadata>

                              <![CDATA[

                              [HostComponent("spark.components.TextInput")]

                              ]]>

                            </fx:Metadata>

                             

                            <fx:Script fb:purpose="styling">

                              <![CDATA[

                               import mx.core.FlexVersion;

                              

                               private var paddingChanged:Boolean;

                              

                            /*   static private const exclusions:Array = ["background", "textDisplay", "promptDisplay", "border"];

                               static private const exclusions_4_0:Array = ["background", "textDisplay", "promptDisplay"];

                              

                               override public function get colorizeExclusions():Array  {

                                if (FlexVersion.compatibilityVersion < FlexVersion.VERSION_4_5) {

                                 return exclusions_4_0;

                                }

                                return exclusions;

                               } */

                              

                               static private const contentFill:Array = ["bgFill"];

                               override public function get contentItems():Array {return contentFill};

                              

                               override protected function commitProperties():void {

                                super.commitProperties();

                               

                                if (paddingChanged) {

                                 updatePadding();

                                 paddingChanged = false;

                                }

                               }

                               override protected function initializationComplete():void {

                                useChromeColor = true;

                                super.initializationComplete();

                               }

                              

                               override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {

                                if (getStyle("borderVisible") == true) {

                                 border.visible = true;

                                 shadow.visible = true;

                                 background.left = background.top = background.right = background.bottom = 1;

                                 textDisplay.left = textDisplay.top = textDisplay.right = textDisplay.bottom = 1;

                                 if (promptDisplay)

                                 {

                                  promptDisplay.setLayoutBoundsSize(unscaledWidth - 2, unscaledHeight - 2);

                                  promptDisplay.setLayoutBoundsPosition(1, 1);

                                 }

                                }

                                else

                                {

                                 border.visible = false;

                                 shadow.visible = false;

                                 background.left = background.top = background.right = background.bottom = 0;

                                 textDisplay.left = textDisplay.top = textDisplay.right = textDisplay.bottom = 0;

                                 if (promptDisplay)

                                 {

                                  promptDisplay.setLayoutBoundsSize(unscaledWidth, unscaledHeight);

                                  promptDisplay.setLayoutBoundsPosition(0, 0);

                                 }

                                }

                               

                               // borderStroke.color = getStyle("borderColor");

                               // borderStroke.alpha = getStyle("borderAlpha");

                               

                                super.updateDisplayList(unscaledWidth, unscaledHeight);

                               }

                              

                               private function updatePadding():void {

                                if (!textDisplay)

                                 return;

                               

                                var padding:Number;

                               

                                padding = getStyle("paddingLeft");

                                if (textDisplay.getStyle("paddingLeft") != padding)

                                 textDisplay.setStyle("paddingLeft", padding);

                               

                                padding = getStyle("paddingTop");

                                if (textDisplay.getStyle("paddingTop") != padding)

                                 textDisplay.setStyle("paddingTop", padding);

                               

                                padding = getStyle("paddingRight");

                                if (textDisplay.getStyle("paddingRight") != padding)

                                 textDisplay.setStyle("paddingRight", padding);

                               

                                padding = getStyle("paddingBottom");

                                if (textDisplay.getStyle("paddingBottom") != padding)

                                 textDisplay.setStyle("paddingBottom", padding);

                               

                                if (!promptDisplay)

                                 return;

                               

                                padding = getStyle("paddingLeft");

                                if (promptDisplay.getStyle("paddingLeft") != padding)

                                 promptDisplay.setStyle("paddingLeft", padding);

                               

                                padding = getStyle("paddingTop");

                                if (promptDisplay.getStyle("paddingTop") != padding)

                                 promptDisplay.setStyle("paddingTop", padding);

                               

                                padding = getStyle("paddingRight");

                                if (promptDisplay.getStyle("paddingRight") != padding)

                                 promptDisplay.setStyle("paddingRight", padding);

                               

                                padding = getStyle("paddingBottom");

                                if (promptDisplay.getStyle("paddingBottom") != padding)

                                 promptDisplay.setStyle("paddingBottom", padding);

                               }

                              

                               override public function styleChanged(styleProp:String):void {

                                var allStyles:Boolean = !styleProp || styleProp == "styleName";

                               

                                super.styleChanged(styleProp);

                               

                                if (allStyles || styleProp.indexOf("padding") == 0)

                                {

                                 paddingChanged = true;

                                 invalidateProperties();

                                }

                               }

                              ]]>

                            </fx:Script>

                             

                            <fx:Script>

                              <![CDATA[

                             

                               //private static const focusExclusions:Array = ["textDisplay"];

                              

                               //override public function get focusSkinExclusions():Array { return focusExclusions;};

                              ]]>

                            </fx:Script>

                             

                            <s:states>

                              <s:State name="normal"/>

                              <s:State name="disabled" stateGroups="disabledStates"/>

                              <s:State name="normalWithPrompt"/>

                              <s:State name="disabledWithPrompt" stateGroups="disabledStates"/>

                            </s:states>

                             

                            <!-- border -->

                            <s:Rect left="-1" right="-1" top="-1" bottom="-1" id="border">

                              <s:stroke>    

                               <!--- @private -->

                                <s:LinearGradientStroke id="borderStroke" rotation="-90" weight="2">

                                 <s:GradientEntry color="#ffffff" ratio="0.116564"/>

                                 <s:GradientEntry color="#808080" ratio="0.932515"/>

                                </s:LinearGradientStroke>

                              </s:stroke>

                            </s:Rect>

                             

                            <!-- fill -->

                            <s:Rect id="background" left="1" right="1" top="1" bottom="1">

                              <s:fill>

                               <!--- @private Defines the background fill color. -->

                               <s:SolidColor id="bgFill" color="#EEEFF1" />

                              </s:fill>

                            </s:Rect>

                             

                            <!-- shadow -->

                            <s:Rect left="1" top="1" right="1" height="1" id="shadow">

                              <s:fill>

                               <s:SolidColor color="0x000000" alpha="0.12" />

                              </s:fill>

                            </s:Rect>

                             

                            <!-- text -->

                            <s:RichEditableText id="textDisplay"

                                  verticalAlign="middle"

                                  widthInChars="10"

                                  left="1" right="1" top="1" bottom="1"/>

                             

                            <s:Label id="promptDisplay" maxDisplayedLines="1"

                                verticalAlign="middle"

                                mouseEnabled="false" mouseChildren="false"

                                includeIn="normalWithPrompt,disabledWithPrompt"

                                includeInLayout="false"/>

                             

                            <!-- Added to custom skin to cause prompt text to fade in. -->

                            <s:transitions>

                              <s:Transition toState="normalWithPrompt">

                               <s:Fade targets="{promptDisplay}" duration="500"/>

                              </s:Transition>

                            </s:transitions>

                             

                             

                            </s:SparkSkin>

                            • 12. Re: keyboard won't go up on TextInput focus flex 4.6-iOS
                              simon.oconnor Level 1

                              Yup, same issue here.

                               

                              You would have thought someone at Adobe maybe would have checked an InputText with an iOS device no?

                              • 13. Re: keyboard won't go up on TextInput focus flex 4.6-iOS
                                drkstr_1 Level 4

                                mikmiki, did you copy and paste the mobile TextInputSkin? It would appear you are using the skin from the spark theme instead...

                                • 14. Re: keyboard won't go up on TextInput focus flex 4.6-iOS
                                  PablitoLamb Level 1

                                  Yesterday I ran into this same problem, and i solved it with a tricky solution

                                   

                                   

                                  The solution is set stage.focus = txt, and then, call two consecutive calllaters to call txt.requestSoftKeyboard method, and the keyboard magically appears

                                   

                                   

                                  I tested it on a Ipad mini and works

                                   

                                   

                                  here the code

                                   

                                  /////////////////

                                   

                                  public function setFocusOnComponent():void{

                                   

                                            stage.focus = txt;

                                   

                                            callLater(callLaterFocusStage1);

                                   

                                  }

                                   

                                   

                                  private function callLaterFocusStage1():void{

                                            callLater(callLaterFocusStage2);

                                  }

                                   

                                  private function callLaterFocusStage2():void{

                                            txt.requestSoftKeyboard();

                                  }