You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ma...@apache.org on 2013/11/25 01:15:24 UTC

[2/2] git commit: [flex-sdk] [refs/heads/develop] - FIX FLEX-33166 Mobile TextInput with native StageTextInput cannot be included in scrollable forms FIX SUB: https://issues.apache.org/jira/browse/FLEX-33931 Cannot initiate view scrolling by touching

FIX  FLEX-33166 Mobile TextInput with native StageTextInput cannot be included in scrollable forms
  FIX SUB: https://issues.apache.org/jira/browse/FLEX-33931 Cannot initiate view scrolling by touching a TextInput/TextArea
Manually tested on:
- iOS6 (ipad 2)
- iOS7 (iPad 3)
- ADL on Windows
Mustella test pass:
mobile/components/TextInput
mobile/components/TextArea
mobile/SoftKeyboard
mobile/components/ActionBar


Project: http://git-wip-us.apache.org/repos/asf/flex-sdk/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-sdk/commit/249b38b7
Tree: http://git-wip-us.apache.org/repos/asf/flex-sdk/tree/249b38b7
Diff: http://git-wip-us.apache.org/repos/asf/flex-sdk/diff/249b38b7

Branch: refs/heads/develop
Commit: 249b38b7c8e4d6b5a464eb5d0ea4af3eb8a5393e
Parents: e566d3e
Author: mamsellem <ma...@systar.com>
Authored: Mon Nov 25 01:01:21 2013 +0100
Committer: mamsellem <ma...@systar.com>
Committed: Mon Nov 25 01:14:48 2013 +0100

----------------------------------------------------------------------
 .../supportClasses/ScrollableStageText.as       | 70 +++++++++++----
 .../skins/mobile/ScrollingStageTextAreaSkin.as  | 18 ----
 .../skins/mobile/ScrollingStageTextInputSkin.as | 18 ----
 .../supportClasses/SkinnableTextBase.as         | 94 +++++++++++---------
 .../src/spark/core/IProxiedStageTextWrapper.as  | 43 +++++++++
 5 files changed, 145 insertions(+), 98 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/249b38b7/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ScrollableStageText.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ScrollableStageText.as b/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ScrollableStageText.as
index b09bb47..b777461 100644
--- a/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ScrollableStageText.as
+++ b/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ScrollableStageText.as
@@ -26,7 +26,6 @@ import flash.display.PixelSnapping;
 import flash.events.Event;
 import flash.events.FocusEvent;
 import flash.events.KeyboardEvent;
-import flash.events.MouseEvent;
 import flash.events.SoftKeyboardEvent;
 import flash.geom.Matrix;
 import flash.geom.Point;
@@ -47,15 +46,16 @@ import mx.core.LayoutDirection;
 import mx.core.UIComponent;
 import mx.core.mx_internal;
 import mx.events.FlexEvent;
-import mx.events.TouchInteractionEvent;
-import mx.managers.FocusManager;
 import mx.managers.SystemManager;
 import mx.utils.MatrixUtil;
 
 import spark.components.Application;
+import spark.core.IProxiedStageTextWrapper;
 import spark.core.ISoftKeyboardHintClient;
 import spark.events.TextOperationEvent;
 
+import flash.text.StageTextInitOptions;
+
 use namespace mx_internal;
 
 //--------------------------------------
@@ -309,7 +309,7 @@ use namespace mx_internal;
  *  @playerversion AIR 3.0
  *  @productversion Flex 4.12
  */
-public class ScrollableStageText extends UIComponent  implements IStyleableEditableText, ISoftKeyboardHintClient
+public class ScrollableStageText extends UIComponent  implements IStyleableEditableText, ISoftKeyboardHintClient , IProxiedStageTextWrapper
 {
 
     //--------------------------------------------------------------------------
@@ -336,6 +336,12 @@ public class ScrollableStageText extends UIComponent  implements IStyleableEdita
      */
     protected static var defaultStyles:Object;
 
+    /* Last stage text that received the focus.  This is used by tempStageText to use the same keyboard type*/
+    protected static var lastFocusedStageText: StageText;
+
+    /* this is a hidden stage text that gets the focus to prevent soft keyboard from hiding*/
+    protected static var hiddenFocusStageText: StageText = null;
+
     /**
      * when set to true, displays the proxy images with a purple background, to help debugging proxy vs stageText usage.
      */
@@ -665,7 +671,10 @@ public class ScrollableStageText extends UIComponent  implements IStyleableEdita
         return _densityScale;
     }
 
-    protected function get showProxy():Boolean {
+    /**
+     * @private
+     */
+    protected function get showsProxy():Boolean {
         return !isEditing;
     }
 
@@ -1343,7 +1352,7 @@ public class ScrollableStageText extends UIComponent  implements IStyleableEdita
             updateViewPort();
         }
 
-        if (invalidateProxyFlag && showProxy)
+        if (invalidateProxyFlag && showsProxy)
         {
             invalidateProxyFlag = false;
             updateProxy();
@@ -1364,7 +1373,8 @@ public class ScrollableStageText extends UIComponent  implements IStyleableEdita
     {
         if (stageText != null)
         {
-            stageText.assignFocus();      // will trigger stageTextfocusIn
+            stageText.assignFocus();
+            lastFocusedStageText = stageText;
         }
     }
 
@@ -1732,7 +1742,6 @@ public class ScrollableStageText extends UIComponent  implements IStyleableEdita
             savedSelectionActiveIndex = 0;
         }
 
-        addEventListener(TouchInteractionEvent.TOUCH_INTERACTION_STARTING, touchStartingHandler);
         if (stageText != null)
         {
             stageText.addEventListener(Event.CHANGE, stageText_changeHandler);
@@ -1758,7 +1767,6 @@ public class ScrollableStageText extends UIComponent  implements IStyleableEdita
         savedSelectionActiveIndex = stageText.selectionActiveIndex;
 
         stageText.stage = null;
-        addEventListener(TouchInteractionEvent.TOUCH_INTERACTION_STARTING, touchStartingHandler);
         stageText.removeEventListener(Event.CHANGE, stageText_changeHandler);
         stageText.removeEventListener(Event.COMPLETE, stageText_completeHandler);
         stageText.removeEventListener(FocusEvent.FOCUS_IN, stageText_focusInHandler);
@@ -1807,13 +1815,6 @@ public class ScrollableStageText extends UIComponent  implements IStyleableEdita
 
 
 
-    private function touchStartingHandler(event: Event): void
-    {
-        // don't allow touch scrolling while editing (of the StageText will stay in place)
-        if (isEditing)
-            event.preventDefault();
-    }
-
     private function stageText_focusInHandler(event:FocusEvent):void
     {
           if (!isEditing){
@@ -1830,7 +1831,7 @@ public class ScrollableStageText extends UIComponent  implements IStyleableEdita
     {
         if (isEditing)
         {
-            endTextEdit();
+            callLater(endTextEdit);
         }
               // Focus events are documented as bubbling. However, all events coming
               // from StageText are set to not bubble. So we need to create an
@@ -1947,15 +1948,46 @@ public class ScrollableStageText extends UIComponent  implements IStyleableEdita
         var parentSkin: UIComponent = this.parent.parent as UIComponent;
         return    parentSkin ? parentSkin.id : "-" ;
     }
+
+    /**
+     * @inheritDoc
+     */
+    public function prepareForTouchScroll(): void
+    {
+        endTextEdit();
+        // hide temp softkeyboard, if any
+        if (hiddenFocusStageText)  {
+            hiddenFocusStageText.visible = false;
+        }
+
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function keepSoftKeyboardActive(): void
+    {
+        // create temp stage text  if does not exist
+        if (!hiddenFocusStageText)
+        {
+            hiddenFocusStageText = new StageText(new StageTextInitOptions(false));
+            hiddenFocusStageText.viewPort = new Rectangle(0, 0, 0, 0);
+            hiddenFocusStageText.stage = stage;
+        }
+
+        if (lastFocusedStageText)
+            hiddenFocusStageText.softKeyboardType = lastFocusedStageText.softKeyboardType;
+        hiddenFocusStageText.visible = true;
+        hiddenFocusStageText.assignFocus();
+    }
 }
 }
 
 import flash.events.TimerEvent;
 import flash.text.StageText;
-import flash.text.StageTextInitOptions;
 import flash.utils.Dictionary;
 import flash.utils.Timer;
-
+import flash.text.StageTextInitOptions;
 import spark.components.supportClasses.ScrollableStageText;
 
 class StageTextPool

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/249b38b7/frameworks/projects/mobiletheme/src/spark/skins/mobile/ScrollingStageTextAreaSkin.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/mobile/ScrollingStageTextAreaSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/mobile/ScrollingStageTextAreaSkin.as
index 1990a4a..2b8d02a 100644
--- a/frameworks/projects/mobiletheme/src/spark/skins/mobile/ScrollingStageTextAreaSkin.as
+++ b/frameworks/projects/mobiletheme/src/spark/skins/mobile/ScrollingStageTextAreaSkin.as
@@ -42,30 +42,12 @@ public class ScrollingStageTextAreaSkin extends StageTextAreaSkin
     public function ScrollingStageTextAreaSkin()
     {
         super();
-        addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
     }
 
     override protected function createTextDisplay():IStyleableEditableText
     {
         return new ScrollableStageText(multiline);
-
-    }
-
-    /** @private
-     *  We have to force focus to the text display when user user in the padding area of the TextInput.
-    we do this hack  in the skin instead of the hostComponent TextInput to not impact the behavior of other skins
-      */
-    override public function set owner(value: DisplayObjectContainer): void
-    {
-        super.owner = value;
-        if (owner){
-            owner.mouseEnabled = false;
-        }
     }
 
-    private function mouseDownHandler(event: MouseEvent): void
-    {
-        textDisplay.setFocus();
-    }
 }
 }

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/249b38b7/frameworks/projects/mobiletheme/src/spark/skins/mobile/ScrollingStageTextInputSkin.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/mobile/ScrollingStageTextInputSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/mobile/ScrollingStageTextInputSkin.as
index 61e37df..c42c893 100644
--- a/frameworks/projects/mobiletheme/src/spark/skins/mobile/ScrollingStageTextInputSkin.as
+++ b/frameworks/projects/mobiletheme/src/spark/skins/mobile/ScrollingStageTextInputSkin.as
@@ -42,30 +42,12 @@ public class ScrollingStageTextInputSkin extends StageTextInputSkin
     public function ScrollingStageTextInputSkin()
     {
         super();
-        addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
     }
 
     override protected function createTextDisplay():IStyleableEditableText
     {
         return new ScrollableStageText(multiline);
-
-    }
-
-    /** @private
-     *  We have to force focus to the text display when user user in the padding area of the TextInput.
-    we do this hack  in the skin instead of the hostComponent TextInput to not impact the behavior of other skins
-      */
-    override public function set owner(value: DisplayObjectContainer): void
-    {
-        super.owner = value;
-        if (owner){
-            owner.mouseEnabled = false;
-        }
     }
 
-    private function mouseDownHandler(event: MouseEvent): void
-    {
-        textDisplay.setFocus();
-    }
 }
 }

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/249b38b7/frameworks/projects/spark/src/spark/components/supportClasses/SkinnableTextBase.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/spark/src/spark/components/supportClasses/SkinnableTextBase.as b/frameworks/projects/spark/src/spark/components/supportClasses/SkinnableTextBase.as
index d43ca69..6b6db26 100644
--- a/frameworks/projects/spark/src/spark/components/supportClasses/SkinnableTextBase.as
+++ b/frameworks/projects/spark/src/spark/components/supportClasses/SkinnableTextBase.as
@@ -49,6 +49,7 @@ import spark.components.RichEditableText;
 import spark.components.TextSelectionHighlighting;
 import spark.core.IDisplayText;
 import spark.core.IEditableText;
+import spark.core.IProxiedStageTextWrapper;
 import spark.core.ISoftKeyboardHintClient;
 import spark.events.TextOperationEvent;
 
@@ -443,11 +444,11 @@ public class SkinnableTextBase extends SkinnableComponent
      *  @private
      *  True if we received a mouseDown and we haven't receieved a mouseUp yet
      */
-    private var isMouseDown:Boolean = false;
+    private var isTouchMouseDown:Boolean = false;
     
     /**
      *  @private
-     *  True if setFocus is called while isMouseDown is true
+     *  True if setFocus is called while isTouchMouseDown is true
      */
     private var delaySetFocus:Boolean = false;
     
@@ -455,7 +456,7 @@ public class SkinnableTextBase extends SkinnableComponent
      *  @private
      *  The target from the current mouseDown event
      */
-    private var mouseDownTarget:InteractiveObject;
+    private var touchMouseDownTarget:InteractiveObject;
     
     /**
      *  @private
@@ -1721,6 +1722,8 @@ public class SkinnableTextBase extends SkinnableComponent
                 addEventListener(MouseEvent.MOUSE_DOWN, touchMouseDownHandler);
                 addEventListener(TouchInteractionEvent.TOUCH_INTERACTION_STARTING,
                         touchInteractionStartingHandler);
+                addEventListener(TouchInteractionEvent.TOUCH_INTERACTION_START,
+                        touchInteractionStartHandler);
                 touchHandlersAdded = true;
             }
             else if (getStyle("interactionMode") == InteractionMode.MOUSE && touchHandlersAdded)
@@ -1728,6 +1731,8 @@ public class SkinnableTextBase extends SkinnableComponent
                 removeEventListener(MouseEvent.MOUSE_DOWN, touchMouseDownHandler);
                 removeEventListener(TouchInteractionEvent.TOUCH_INTERACTION_STARTING,
                         touchInteractionStartingHandler);
+                removeEventListener(TouchInteractionEvent.TOUCH_INTERACTION_START,
+                        touchInteractionStartHandler);
                 touchHandlersAdded = false;
             }
         }
@@ -1854,28 +1859,17 @@ public class SkinnableTextBase extends SkinnableComponent
      */
     override public function setFocus():void
     {
-        // If the mouse is down, then we don't want the TextField to open the soft keyboard until mouse up. 
+        // If the mouse is down, then we don't want the TextField to open the soft keyboard until mouse up.
+        // we also want to prevent the keyboard from hiding until the next mouse up focus, or touch scroll.
         // Otherwise, this was called programmatically and we want the soft keyboard to appear immediately.
-        // Note that isMouseDown can only be true when we are in InteractionMode == TOUCH. 
+        // Note that isTouchMouseDown can only be true when we are in InteractionMode == TOUCH.
         if (textDisplay)
         {
-            if (isMouseDown)
+            if (isTouchMouseDown)
             {
                 delaySetFocus = true;
-                
-                // Cancelling an ACTIVATING event will close the softKeyboard if it is 
-                // currently active on iOS only. Add a check to only cancel the event
-                // if the softKeyboard is not active. Otherwise, the softKeyboard will
-                // close if you press on the skin of a text component.
-                var topLevelApp:Application = FlexGlobals.topLevelApplication as Application;
-                var cancelEvent:Boolean = !(topLevelApp && topLevelApp.isSoftKeyboardActive);
-                if (cancelEvent)
-                    addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATING, softKeyboardActivatingHandler);
-                
-                textDisplay.setFocus();
-                
-                if (cancelEvent)
-                    removeEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATING, softKeyboardActivatingHandler);
+                if (textDisplay is IProxiedStageTextWrapper)
+                  IProxiedStageTextWrapper(textDisplay).keepSoftKeyboardActive();
             }
             else
             {
@@ -2585,8 +2579,8 @@ public class SkinnableTextBase extends SkinnableComponent
      */  
     private function touchMouseDownHandler(event:MouseEvent):void
     {
-        isMouseDown = true;
-        mouseDownTarget = event.target as InteractiveObject;
+        isTouchMouseDown = true;
+        touchMouseDownTarget = event.target as InteractiveObject;
         
         // If we already have focus, make sure to open soft keyboard
         // on mouse up
@@ -2602,7 +2596,7 @@ public class SkinnableTextBase extends SkinnableComponent
     
     /**
      * @private
-     * Called if we are in touch interaction mode and a mouseUp occurs on the stage while isMouseDown is true
+     * Called if we are in touch interaction mode and a mouseUp occurs on the stage while isTouchMouseDown is true
      */ 
     private function touchMouseUpHandler(event:Event):void
     {        
@@ -2617,51 +2611,65 @@ public class SkinnableTextBase extends SkinnableComponent
         */
         if ((event.target is DisplayObject && contains(DisplayObject(event.target)))
             && (delaySetFocus ||
-             (mouseDownTarget == textDisplay && event.target != textDisplay)))
+             (touchMouseDownTarget == textDisplay && event.target != textDisplay)))
         {
             if (textDisplay)
                 textDisplay.setFocus();
         }
 
-        clearMouseDownState();
+        clearTouchMouseDownState();
     }
-       
+
+    /**
+     * @private
+     * Called if we are inside of a Scroller and the user is about to  start a scroll gesture.
+     * ask displayDisplay to show its proxy
+     */
+    private function touchInteractionStartingHandler(event: TouchInteractionEvent): void
+    {
+           if (textDisplay && textDisplay is IProxiedStageTextWrapper){
+               IProxiedStageTextWrapper(textDisplay).prepareForTouchScroll();
+           }
+    }
+
     /**
      * @private
      * Called if we are inside of a Scroller and the user has started a scroll gesture
      */
-    private function touchInteractionStartingHandler(event:TouchInteractionEvent):void
+    private function touchInteractionStartHandler(event:TouchInteractionEvent):void
     {
-        //   don't allow initiating scrolling from a TextInput on mobile anymore
-          event.preventDefault();
-    }    
-    
+        // if in iOS and keyboard is up and scrolling is occurring, drop the keyboard
+        var topLevelApp:Application = FlexGlobals.topLevelApplication as Application;
+        if (isIOS && topLevelApp && topLevelApp.isSoftKeyboardActive && editable)
+        {
+            // set focus
+            stage.focus = null;
+        }
+
+        // Clear out the state because starting a scroll gesture should never
+        // open the soft keyboard
+        clearTouchMouseDownState();
+    }
+
     /**
      * @private
      * Helper function to clear the state if the mouse is up or we started as scroll gesture
      */
-    private function clearMouseDownState():void
+    private function clearTouchMouseDownState():void
     {
-        if (isMouseDown)
+        if (isTouchMouseDown)
         {
             systemManager.getSandboxRoot().removeEventListener(
                 MouseEvent.MOUSE_UP, touchMouseUpHandler, false);
             systemManager.getSandboxRoot().removeEventListener(
                 SandboxMouseEvent.MOUSE_UP_SOMEWHERE, touchMouseUpHandler, false);
-            isMouseDown = false;
+            isTouchMouseDown = false;
             delaySetFocus = false;
-            mouseDownTarget = null;
+            touchMouseDownTarget = null;
         }
     }
     
-    /**
-     * @private
-     */
-    private function softKeyboardActivatingHandler(event:SoftKeyboardEvent):void
-    {
-        event.preventDefault();
-    }
-    
+
     /**
      *  @private
      *  Called when the RichEditableText dispatches a 'selectionChange' event.

http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/249b38b7/frameworks/projects/spark/src/spark/core/IProxiedStageTextWrapper.as
----------------------------------------------------------------------
diff --git a/frameworks/projects/spark/src/spark/core/IProxiedStageTextWrapper.as b/frameworks/projects/spark/src/spark/core/IProxiedStageTextWrapper.as
new file mode 100644
index 0000000..c806fef
--- /dev/null
+++ b/frameworks/projects/spark/src/spark/core/IProxiedStageTextWrapper.as
@@ -0,0 +1,43 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package spark.core
+{
+
+/**   This interface defines properties for mobile wrapper classes of StageText that need to handle touch scrolling and soft keyboard.
+ *
+ */
+public interface IProxiedStageTextWrapper
+{
+
+    /**
+     * this method is called before a touch scroll is about to occur, so that component can hide the StageText and show the proxies
+     *  @see spark.components.supportClasses.ScrollableStageText#prepareForTouchScroll()
+     */
+  function prepareForTouchScroll( ): void;
+
+    /**
+     * this method is called between the time a text input get out of focus and the next  text input  gets in focus
+     * to prevent the soft keyboard from disappearing.
+     * @see spark.components.supportClasses.ScrollableStageText#keepSoftKeyboardActive()
+      */
+  function keepSoftKeyboardActive( ): void ;
+
+}
+}