         // if we have an estimated width, use it here.  Otherwise, we'll keep it 
         // the same width as it was before
         if (!isNaN(estimatedWidth))
-            textDisplay.width = estimatedWidth - paddingTop - paddingBottom;
-        
-        measuredHeight = Math.max(layoutMeasuredHeight, getElementPreferredHeight(textDisplay) + paddingTop + paddingBottom);
+            textDisplayGroup.width = estimatedWidth;
+        
+        measuredHeight = Math.max(layoutMeasuredHeight, textDisplay.measuredTextSize.y + paddingTop + paddingBottom);
+    }
+    
+    /**
+     * @private
+     */
+    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
+    {
+        drawBackground(unscaledWidth, unscaledHeight);
+        
+        // position & size border
+        if (border)
+        {
+            setElementSize(border, unscaledWidth, unscaledHeight);
+            setElementPosition(border, 0, 0);
+        }
+        
+        setElementSize(scroller, unscaledWidth, unscaledHeight);
+        setElementPosition(scroller, 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");
+        
+        textDisplayGroup.paddingLeft = paddingLeft;
+        textDisplayGroup.paddingRight = paddingRight;
+        textDisplayGroup.paddingTop = paddingTop;
+        textDisplayGroup.paddingBottom = paddingBottom;
+        
+        var unscaledTextWidth:Number = unscaledWidth - paddingLeft - paddingRight;
+        
+        // set width first to measure height correctly
+        textDisplay.width = unscaledTextWidth;
+        
+        var unscaledTextHeight:Number = unscaledHeight - paddingTop - paddingBottom;
+        var textHeight:Number = unscaledTextHeight;
+        
+        // TextField height should match it's content or the TextArea bounds
+        // iOS special case to prevent Flex Scroller scrolling
+        if (!_isIOS || !textDisplay.editable)
+            textHeight = Math.max(textDisplay.measuredTextSize.y, textHeight);
+        
+        setElementSize(textDisplay, unscaledTextWidth, textHeight);
+        
+        // size the Group to the StyleableTextField plus padding
+        setElementSize(textDisplayGroup, unscaledWidth, paddingTop + textHeight + paddingBottom);
+        
+        if (promptDisplay)
+        {
+            promptDisplay.commitStyles();
+            setElementSize(promptDisplay, unscaledTextWidth, unscaledTextHeight);
+            setElementPosition(promptDisplay, paddingLeft, paddingTop);
+        }
+    }
+    
+    private function caret_changeHandler(event:Event):void
+    {
+        // TODO (jasonsj): caret positioning on iOS
+        // textDisplayGroup.verticalScrollPosition = textDisplay.getCharBoundaries(textDisplay.caretIndex).y;
     }
     
     /**
      *  @private
-     *  
-     *  @langversion 3.0
-     *  @playerversion Flash 10.2
-     *  @playerversion AIR 2.0
-     *  @productversion Flex 4.5
-     */
-    override public function setEstimatedSize(estimatedWidth:Number = NaN, 
-                                              estimatedHeight:Number = NaN,
-                                              invalidateSizeAllowed:Boolean = true):void
-    {
-        var oldcw:Number = this.estimatedWidth;
-        var oldch:Number = this.estimatedHeight;
-        
-        super.setEstimatedSize(estimatedWidth, estimatedHeight, invalidateSizeAllowed);
-        
-        var sameWidth:Boolean = isNaN(estimatedWidth) && isNaN(oldcw) || estimatedWidth == oldcw;
-        var sameHeight:Boolean = isNaN(estimatedHeight) && isNaN(oldch) || estimatedHeight == oldch;
-        if (!(sameHeight && sameWidth))
-        {
-            if (!isNaN(explicitWidth) &&
-                !isNaN(explicitHeight))
-                return;
-            
-            if (invalidateSizeAllowed)
-                invalidateSize();
-        }
-    }
-    
-    /**
-     *  @private
-     *  We override the setLayoutBoundsSize to determine whether to perform
-     *  text reflow. This is a convenient place, as the layout passes NaN
-     *  for a dimension not constrained to the parent.
-     */
-    override public function setLayoutBoundsSize(width:Number,
-                                                 height:Number,
-                                                 postLayoutTransform:Boolean = true):void
-    {
-        var newEstimates:Boolean = false;
-        var cw:Number = estimatedWidth;
-        var ch:Number = estimatedHeight;
-        var oldcw:Number = cw;
-        var oldch:Number = ch;
-        // we got lied to, probably the constraints weren't accurate or
-        // couldn't be computed
-        if (!isNaN(width))
-        {
-            if (isNaN(estimatedWidth) || width != estimatedWidth)
-            {
-                cw = width;
-                newEstimates = true;
-            }
-        }
-        // we got lied to, probably the constraints weren't accurate or
-        // couldn't be computed
-        if (!isNaN(height))
-        {
-            if (isNaN(estimatedHeight) || height != estimatedHeight)
-            {
-                ch = height;
-                newEstimates = true;
-            }
-        }
-        if (newEstimates)
-        {
-            setEstimatedSize(cw, ch);
-            
-            // re-measure with the new estimated size
-            UIComponentGlobals.layoutManager.validateClient(this, true);
-            
-            // set estimated size back to what it was
-            setEstimatedSize(oldcw, oldch, false);
-        }
-        
-        super.setLayoutBoundsSize(width, height, postLayoutTransform);
-    }
-    
-    /**
-     *  @private
      */
     private function textDisplay_changeHandler(event:Event):void
     {
-        invalidateSize();
+        textDisplayGroup.invalidateSize();
     }
 }
 }

use namespace mx_internal;

/**
 *  ActionScript-based skin for TextArea components in mobile applications.
 * 

    //
    //--------------------------------------------------------------------------
    
    private var textDisplayGroup:VGroup;

    private var _isIOS:Boolean;
    
    /**
     *  @private
     */
    override protected function createChildren():void
    {
        if (!textDisplay)
        {
            // wrap StyleableTextField in UIComponent
            textDisplay = StyleableTextField(createInFontContext(StyleableTextField));
            textDisplay.styleName = this;
            textDisplay.multiline = true;
            textDisplay.editable = true;
            textDisplay.wordWrap = true;
            textDisplay.addEventListener(Event.CHANGE, textDisplay_changeHandler);
            textDisplay.addEventListener(FlexEvent.VALUE_COMMIT, textDisplay_changeHandler);
            
            // on iOS, resize the TextField and let the native control handle scrolling
            _isIOS = (Capabilities.version.indexOf("IOS") == 0);
            
            // wrap StyleableTextComponent in Group for viewport
            textDisplayGroup = new VGroup();
            textDisplayGroup.clipAndEnableScrolling = true;
            textDisplayGroup.addElement(textDisplay);
            
            // scroll to the caret position
            textDisplay.addEventListener(Event.CHANGE, caret_changeHandler);
            textDisplay.addEventListener(FlexEvent.VALUE_COMMIT, caret_changeHandler);
        }
        
        if (!scroller)
        {
            scroller = new Scroller();
            scroller.minViewportInset = 0;
            scroller.measuredSizeIncludesScrollBars = false;
            addChild(scroller);
        }
        
        if (!scroller.viewport)
            scroller.viewport = textDisplayGroup;
        
        super.createChildren();
    }
    
    /**
