Flex TextArea and TextInput on mobile not positioned correctly

I had two problems when working with TextArea and TextInput on mobile components, I don't know how to solve them. First, the TextArea text is not positioned correctly, and second, it overlaps other components.

Problems arise when the TextArea is in the Scroller (or the soft keyboard activates and moves the position of the TextArea).

This can be seen if you added the code to the mobile app:

<s:Scroller width="100%" height="100%" top="100" bottom="100">
    <s:VGroup width="50%">
        <s:Button label="" height="600" width="440"/>
        <s:TextArea id="testing" />
        <s:TextArea id="testing2" />
        <s:Button label="" height="800" width="440"/>
    </s:VGroup>
</s:Scroller>

      

The first image is an attachment with some text.

enter image description here

In the second image, I have scrolled a few. When I scrolled down, notice that the text stays in the same place (it's on top of the button that was above it)!

enter image description here

CAVEAT :
If I drop the view, the text is immediately placed in the right place (in the AIR simulator) and positioned correctly when the content settles to the final position (on mobile, the text seems to fade out until the final resting location). This is good news as something happens when thrown, which doesn't happen when manually pressing, dragging and releasing (not throwing), or when activating the soft keyboard.

Unfortunately text can still appear on top of all other content, ignoring the scroller mask, but I can live with that if the other first issue is fixed.

UPDATE
I can get the text to move in the correct position if I set width to width + 1. It doesn't work because I don't want to resize it explicitly. I tried to invalidate and nothing works. Here is the code I tried on the softKeyboardActivating event. Expand width = width + 1 to see her "work":

    <s:TextArea id="testing" softKeyboardActivate="testing_softKeyboardActivateHandler(event)"/>

<fx:Script>
    <![CDATA[
        import mx.core.IInvalidating;
        protected function testing_softKeyboardActivateHandler(event:SoftKeyboardEvent):void {
            trace("Activating");
            /*testing.invalidateProperties();
            testing.invalidateDisplayList();
            testing.invalidateSize();
            testing.validateNow();
            parentGroup.validateNow();
            scroller.validateNow();*/
            // testing.invalidateParentSizeAndDisplayList();
            //IInvalidating(testing.parent).invalidateSize();
            //IInvalidating(testing.parent).invalidateDisplayList();
            //testing.width = NaN;
            //testing.width = testing.width+1;
        }
    ]]>
</fx:Script>

      

UPDATE 2 :
This code works, but it's a hack and it is much slower than the code the scroller uses when viewing the view:

protected function testing_softKeyboardActivateHandler(event:SoftKeyboardEvent):void {
    StageTextAreaSkin2(testing.skin).styleChanged("styleName");
}

      

UPDATE 3
I added a workaround in the answers section below, but this is a hack. In addition, when in the correct position, it also disguises itself correctly. So good and good. However, I am still looking for the right way to do this.

This has been tested with Flex 4.6, AIR 3.5 on Mac in the AIR simulator, iPhone 5 and Android Nexus 7.

+3


source to share


2 answers


Here's a workaround. Create an MXML file (usually StageTextArea.mxml) and put this code in it.



<?xml version="1.0" encoding="utf-8"?>
<s:TextArea xmlns:fx="http://ns.adobe.com/mxml/2009" 
            xmlns:s="library://ns.adobe.com/flex/spark"
            softKeyboardActivate="softKeyboardActivateHandler(event)"
            softKeyboardDeactivate="softKeyboardDeactivateHandler(event)"
            added="addedHandler(event)" 
            removed="removedHandler(event)">

    <!-- USAGE 
        <controls:StageTextArea id="myTextArea" parentScroller="{myScroller}"/>
    -->

    <fx:Script>
        <![CDATA[
            import mx.events.PropertyChangeEvent;

            import spark.components.Scroller;

            private var _parentScroller:Scroller;

            public function get parentScroller():Scroller {
                return _parentScroller;
            }

            /**
             * Adds a listener to an ancestor scroller. 
             * */
            [Bindable]
            public function set parentScroller(value:Scroller):void {

                if (value && value.viewport) {
                    value.viewport.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, handle, false, 0, true);
                }
                if (value==null && _parentScroller) {
                    value.viewport.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE, handle);
                }
                _parentScroller = value;
            }


            /**
             * Add listener to parent component when added to the display list
             * */
            protected function addedHandler(event:Event):void {
                if (event.target==event.currentTarget) { 
                    // we could "discover" the scroller here if we wanted
                    // or we could just use parentScroller property
                    owner.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, handle, false, 0, true);
                }
            }

            /**
             * Remove listener to parent component when removed to the display list
             * */
            protected function removedHandler(event:Event):void {
                if (event.target==event.currentTarget) {
                    owner.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE, handle);
                }
            }

            /**
             * Handle parent or ancestor scroll position changes
             */
            private function handle(e:PropertyChangeEvent):void {
                if (e.source == e.target && e.property == "verticalScrollPosition") {
                    //trace(e.property, "changed to", e.newValue);
                    updateTextFieldPosition();
                }
                if (e.source == e.target && e.property == "horizontalScrollPosition") {
                    //trace(e.property, "changed to", e.newValue);
                    updateTextFieldPosition();
                }
            }

            /**
             * Handles when keyboard activates
             * */
            protected function softKeyboardActivateHandler(event:SoftKeyboardEvent):void {
                updateTextFieldPosition();
            }

            /**
             * Handles when keyboard deactivates
             * */
            protected function softKeyboardDeactivateHandler(event:SoftKeyboardEvent):void {
                updateTextFieldPosition();
            }

            /**
             * Updates the native text fields position
             * */
            public function updateTextFieldPosition():void {
                skin.styleChanged("anything"); // force skin class to revalidate
            }

        ]]>
    </fx:Script>

</s:TextArea>

      

+2


source


This is a bug in Flex with built-in text controls. If you include the following in your top-level app, it solves the problem:



<fx:Style>
        @namespace s "library://ns.adobe.com/flex/spark";
        @namespace mx "library://ns.adobe.com/flex/mx";
        @namespace local "*";
        s|TextInput {
            skinClass: ClassReference("spark.skins.mobile.TextInputSkin");
            showPromptWhenFocused:false;
        }
        s|TextArea {
            skinClass: ClassReference("spark.skins.mobile.TextAreaSkin");
        }
</fx:Style>

      

+4


source







All Articles