You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by bi...@apache.org on 2014/11/04 20:16:06 UTC

[16/22] added in Android Skins

http://git-wip-us.apache.org/repos/asf/flex-examples/blob/539852e9/tourdeflexmobile/src/spark/skins/android4/SpinnerListSkin.as
----------------------------------------------------------------------
diff --git a/tourdeflexmobile/src/spark/skins/android4/SpinnerListSkin.as b/tourdeflexmobile/src/spark/skins/android4/SpinnerListSkin.as
new file mode 100644
index 0000000..006fddb
--- /dev/null
+++ b/tourdeflexmobile/src/spark/skins/android4/SpinnerListSkin.as
@@ -0,0 +1,293 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.skins.android4
+{
+	import flash.display.InteractiveObject;
+	
+	import mx.core.ClassFactory;
+	import mx.core.DPIClassification;
+	import mx.core.mx_internal;
+	
+	import spark.components.DataGroup;
+	import spark.components.Scroller;
+	import spark.components.SpinnerList;
+	import spark.components.SpinnerListItemRenderer;
+	import spark.layouts.VerticalSpinnerLayout;
+	import spark.skins.android4.assets.SpinnerListContainerSelectionIndicator;
+	import spark.skins.mobile.supportClasses.MobileSkin;	
+	
+	
+	use namespace mx_internal;
+	/**
+	 *  ActionScript-based skin for the SpinnerList in mobile applications. 
+	 * 
+	 *  @see spark.components.SpinnerList
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion AIR 3
+	 *  @productversion Flex 4.6
+	 */
+	public class SpinnerListSkin extends MobileSkin
+	{
+		/**
+		 *  Constructor.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion AIR 3
+		 *  @productversion Flex 4.6
+		 */
+		public function SpinnerListSkin()
+		{
+			super();
+			
+			selectionIndicatorClass = spark.skins.android4.assets.SpinnerListContainerSelectionIndicator;
+			borderThickness = 1;
+			switch (applicationDPI)
+			{
+				case DPIClassification.DPI_640:
+				{
+					selectionIndicatorHeight = 182;
+					minWidth = 64;
+					borderThickness = 3;
+					break;
+				}
+				case DPIClassification.DPI_480:
+				{
+					selectionIndicatorHeight = 144;
+					minWidth = 48;
+					borderThickness = 2;
+					break;
+				}
+				case DPIClassification.DPI_320:
+				{
+					selectionIndicatorHeight = 96;
+					minWidth = 32;
+					borderThickness = 2;
+					break;
+				}
+				case DPIClassification.DPI_240:
+				{
+					selectionIndicatorHeight = 72;
+					minWidth = 24;
+					borderThickness = 1;
+					break;
+				}
+				case DPIClassification.DPI_120:
+				{
+					selectionIndicatorHeight = 36;
+					minWidth = 12;
+					borderThickness = 0;
+					break;
+				}
+				default:
+				{
+					selectionIndicatorHeight = 48;
+					minWidth = 16;
+					borderThickness = 1;
+				}   
+			}
+			
+		}
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Skin parts 
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  Scroller skin part.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion AIR 3
+		 *  @productversion Flex 4.6
+		 */ 
+		public var scroller:Scroller;
+		
+		/**
+		 *  DataGroup skin part.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion AIR 3
+		 *  @productversion Flex 4.6
+		 */ 
+		public var dataGroup:DataGroup;
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Properties 
+		//
+		//--------------------------------------------------------------------------
+		/** 
+		 *  @copy spark.skins.spark.ApplicationSkin#hostComponent
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion AIR 3
+		 *  @productversion Flex 4.6
+		 */
+		public var hostComponent:SpinnerList;
+		
+		/**
+		 *  Pixel size of the border.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion AIR 3
+		 *  @productversion Flex 4.6
+		 */ 
+		protected var borderThickness:int;
+		
+		/**
+		 *  Class for the selection indicator skin part. 
+		 *       
+		 *  @langversion 3.0
+		 *  @playerversion AIR 3
+		 *  @productversion Flex 4.6
+		 */
+		protected var selectionIndicatorClass:Class;
+		
+		/**
+		 *  Selection indicator skin part. 
+		 *       
+		 *  @langversion 3.0
+		 *  @playerversion AIR 3
+		 *  @productversion Flex 4.6
+		 */
+		protected var selectionIndicator:InteractiveObject;
+		
+		/**
+		 *  Height of the selection indicator.  
+		 *       
+		 *  @langversion 3.0
+		 *  @playerversion AIR 3
+		 *  @productversion Flex 4.6
+		 */
+		protected var selectionIndicatorHeight:Number;
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Overridden Methods 
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @private
+		 */
+		override protected function commitCurrentState():void
+		{
+			super.commitCurrentState();
+			
+			alpha = currentState.indexOf("disabled") == -1 ? 1 : 0.5;
+		}
+		
+		/**
+		 *  @private
+		 */
+		override protected function createChildren():void
+		{           
+			super.createChildren();
+			
+			if (!dataGroup)
+			{
+				// Create data group layout
+				var layout:VerticalSpinnerLayout = new VerticalSpinnerLayout();
+				layout.requestedRowCount = 5;
+				// Create data group
+				dataGroup = new DataGroup();
+				dataGroup.id = "dataGroup";
+				dataGroup.layout = layout;
+				
+				dataGroup.itemRenderer = new ClassFactory(spark.components.SpinnerListItemRenderer);
+			}
+			
+			if (!scroller)
+			{
+				// Create scroller
+				scroller = new Scroller();
+				scroller.id = "scroller";
+				scroller.hasFocusableChildren = false;
+				scroller.ensureElementIsVisibleForSoftKeyboard = false;
+				// Only support vertical scrolling
+				scroller.setStyle("verticalScrollPolicy","on");
+				scroller.setStyle("horizontalScrollPolicy", "off");
+				scroller.setStyle("skinClass", spark.skins.android4.SpinnerListScrollerSkin);
+				
+				addChild(scroller);
+			}
+			
+			if (!selectionIndicator)
+			{
+				// Selection indicator is on top
+				selectionIndicator = new selectionIndicatorClass();
+				selectionIndicator.mouseEnabled = false;
+				addChild(selectionIndicator);
+			}
+			
+			// Associate scroller with data group
+			if (!scroller.viewport)
+				scroller.viewport = dataGroup;
+		}
+		
+		/**
+		 *  @private
+		 */
+		override protected function measure():void
+		{
+			measuredWidth = scroller.getPreferredBoundsWidth() + borderThickness * 2;
+			measuredHeight = scroller.getPreferredBoundsHeight();
+			//add in for selection indicator
+			measuredMinHeight = selectionIndicatorHeight + borderThickness * 4;
+			minHeight = measuredMinHeight;			
+		}
+		
+		/**
+		 *  @private
+		 */
+		override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+		{   
+			super.layoutContents(unscaledWidth, unscaledHeight);			
+			
+			// Scroller
+			setElementSize(scroller, unscaledWidth - borderThickness * 2, unscaledHeight);
+			setElementPosition(scroller, borderThickness, 0);
+			//selection indicator
+			unscaledHeight = Math.max(unscaledHeight, selectionIndicatorHeight + borderThickness * 4);
+			
+			setElementSize(selectionIndicator, unscaledWidth, selectionIndicatorHeight);
+			setElementPosition(selectionIndicator, 0, Math.floor((unscaledHeight - selectionIndicatorHeight) / 2));
+		}
+		
+		/**
+		 *  @private
+		 */
+		override public function styleChanged(styleProp:String):void
+		{
+			// Reinitialize the typical element so it picks up the latest styles
+			// Font styles might impact the size of the SpinnerList
+			if (styleProp != "color" && styleProp != "accentColor")
+			{
+				if (dataGroup)
+					dataGroup.invalidateTypicalItemRenderer();
+			}
+			
+			super.styleChanged(styleProp);
+		}
+		
+	}
+}
+

http://git-wip-us.apache.org/repos/asf/flex-examples/blob/539852e9/tourdeflexmobile/src/spark/skins/android4/SplitViewNavigatorSkin.as
----------------------------------------------------------------------
diff --git a/tourdeflexmobile/src/spark/skins/android4/SplitViewNavigatorSkin.as b/tourdeflexmobile/src/spark/skins/android4/SplitViewNavigatorSkin.as
new file mode 100644
index 0000000..ee06eea
--- /dev/null
+++ b/tourdeflexmobile/src/spark/skins/android4/SplitViewNavigatorSkin.as
@@ -0,0 +1,157 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.skins.android4
+{
+	import mx.core.mx_internal;
+	
+	import spark.components.Callout;
+	import spark.components.Group;
+	import spark.components.SkinnablePopUpContainer;
+	import spark.components.SplitViewNavigator;
+	import spark.layouts.HorizontalLayout;
+	import spark.skins.mobile.supportClasses.MobileSkin;
+	
+	use namespace mx_internal;
+	
+	/**
+	 *  The default skin for the SplitViewNavigator component.  This skin is
+	 *  chromeless and doesn't draw a background, border or separator.  
+	 *  It only contains a single content group with a horizontal layout to hold 
+	 *  the navigators, and a Callout component.  
+	 *  The Callout component uses the default values for its layout properties.
+	 * 
+	 *  @see spark.components.Callout
+	 *  @see spark.components.SplitViewNavigator
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion AIR 3
+	 *  @productversion Flex 4.6
+	 */
+	public class SplitViewNavigatorSkin extends MobileSkin
+	{
+		//--------------------------------------------------------------------------
+		//
+		//  Constructor
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  Constructor.
+		 * 
+		 *  @langversion 3.0
+		 *  @playerversion AIR 3
+		 *  @productversion Flex 4.6
+		 */
+		public function SplitViewNavigatorSkin()
+		{
+			super();
+		}
+		
+		//--------------------------------------------------------------------------
+		//
+		//  SkinParts
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @copy spark.components.SkinnableContainer#contentGroup
+		 */
+		public var contentGroup:Group;
+		
+		/**
+		 *  @copy spark.components.SplitViewNavigator#viewNavigatorPopUp
+		 */ 
+		public var viewNavigatorPopUp:SkinnablePopUpContainer;
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Variables
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @copy spark.skins.spark.ApplicationSkin#hostComponent
+		 */
+		public var hostComponent:SplitViewNavigator;
+		
+		//--------------------------------------------------------------------------
+		//
+		// Overridden Methods
+		//
+		//--------------------------------------------------------------------------
+		/**
+		 *  @private
+		 */
+		override protected function createChildren():void
+		{
+			// Create the layout for the content group
+			var hLayout:HorizontalLayout = new HorizontalLayout();
+			
+			// A gap of 1 is used to reveal a thin line of the background between
+			// each child navigator.  This serves as a divider.  To change the look
+			// of the divider, change the backgroundColor style.
+			hLayout.gap = 1;
+			
+			// Create the contentGroup
+			contentGroup = new Group();
+			contentGroup.id = "contentGroup";
+			contentGroup.layout = hLayout;
+			addChild(contentGroup);
+			
+			// Create the callout but don't add it to display list
+			viewNavigatorPopUp = new Callout();
+			viewNavigatorPopUp.id = "viewNavigatorPopUp";
+		}
+		
+		/**
+		 *  @private
+		 */
+		override protected function measure():void
+		{
+			super.measure();
+			
+			measuredWidth = contentGroup.getPreferredBoundsWidth();
+			measuredHeight = contentGroup.getPreferredBoundsHeight();
+		}
+		
+		/**
+		 *  @private
+		 */
+		override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+		{
+			super.layoutContents(unscaledWidth, unscaledHeight);
+			
+			contentGroup.setLayoutBoundsSize(unscaledWidth, unscaledHeight);
+			contentGroup.setLayoutBoundsPosition(0, 0);
+		}
+		
+		/**
+		 *  @private
+		 */
+		override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+		{
+			// Background is used to draw the divider between each navigator
+			var color:uint = getStyle("backgroundColor");
+			graphics.beginFill(color);
+			graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
+			graphics.endFill();
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-examples/blob/539852e9/tourdeflexmobile/src/spark/skins/android4/StageTextAreaSkin.as
----------------------------------------------------------------------
diff --git a/tourdeflexmobile/src/spark/skins/android4/StageTextAreaSkin.as b/tourdeflexmobile/src/spark/skins/android4/StageTextAreaSkin.as
new file mode 100644
index 0000000..97daa08
--- /dev/null
+++ b/tourdeflexmobile/src/spark/skins/android4/StageTextAreaSkin.as
@@ -0,0 +1,185 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.skins.android4
+{
+
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+import mx.utils.Platform;
+
+import spark.components.TextArea;
+import spark.components.supportClasses.StyleableTextField;
+import spark.skins.android4.supportClasses.StageTextSkinBase;
+
+use namespace mx_internal;
+
+/**
+ *  ActionScript-based skin for TextArea controls in mobile applications that uses a
+ *  StyleableStageText class for the text display. 
+ * 
+ *  @see spark.components.TextArea
+ *  @see spark.components.supportClasses.StyleableStageText
+ * 
+ *  @langversion 3.0
+ *  @playerversion AIR 3.0 
+ *  @productversion Flex 4.6
+ */
+public class StageTextAreaSkin extends StageTextSkinBase
+{
+    //--------------------------------------------------------------------------
+    //
+    //  Class variables
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  The underlying native text control on iOS has internal margins of its
+     *  own. In order to remain faithful to the paddingTop and paddingBottom
+     *  style values that developers may specify, those internal margins need to
+     *  be compensated for. This variable contains size of that compensation in
+     *  pixels.
+     */
+    mx_internal static var iOSVerticalPaddingAdjustment:Number = 5;
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  Constructor.
+     *  
+     *  @langversion 3.0
+     *  @playerversion AIR 3.0
+     *  @productversion Flex 4.6
+     */
+    public function StageTextAreaSkin()
+    {
+        super();
+        multiline = true;
+        
+        switch (applicationDPI)
+        {
+			case DPIClassification.DPI_640:
+			{
+				measuredDefaultHeight = 212;
+				break;
+			}
+			case DPIClassification.DPI_480:
+			{
+				measuredDefaultHeight = 140;
+				break;
+			}
+            case DPIClassification.DPI_320:
+            {
+                measuredDefaultHeight = 106;
+                break;
+            }
+			case DPIClassification.DPI_240:
+			{
+				measuredDefaultHeight = 70;
+				break;
+			}
+			case DPIClassification.DPI_120:
+			{
+				measuredDefaultHeight = 35;
+				break;
+			}
+            default:
+            {
+                measuredDefaultHeight = 48;
+                break;
+            }
+        }
+    }
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Variables
+    //
+    //--------------------------------------------------------------------------
+    
+    /** 
+     *  @copy spark.skins.spark.ApplicationSkin#hostComponent
+     */
+    public var hostComponent:TextArea;  // SkinnableComponent will populate
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden methods
+    //
+    //--------------------------------------------------------------------------
+	
+
+	
+    /**
+     *  @private
+     */
+    override protected function layoutContents(unscaledWidth:Number,  unscaledHeight:Number):void
+    {
+        // base class handles border position & size
+        super.layoutContents(unscaledWidth, unscaledHeight);
+        
+        // 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 = Math.max(0, unscaledWidth - paddingLeft - paddingRight);
+        var unscaledTextHeight:Number = Math.max(0, unscaledHeight - paddingTop - paddingBottom);
+        
+        if (textDisplay)
+        {
+            var verticalPosAdjustment:Number = 0;
+            var heightAdjustment:Number = 0;
+            
+            if (Platform.isIOS)
+            {
+                verticalPosAdjustment = Math.min(iOSVerticalPaddingAdjustment, paddingTop);
+                heightAdjustment = verticalPosAdjustment + Math.min(iOSVerticalPaddingAdjustment, paddingBottom);
+            }
+            
+            textDisplay.commitStyles();
+            setElementSize(textDisplay, unscaledTextWidth, unscaledTextHeight + heightAdjustment);
+            setElementPosition(textDisplay, paddingLeft, paddingTop - verticalPosAdjustment);
+        }
+        
+        if (promptDisplay)
+        {
+            if (promptDisplay is StyleableTextField)
+                StyleableTextField(promptDisplay).commitStyles();
+            
+            setElementSize(promptDisplay, unscaledTextWidth, unscaledTextHeight);
+            setElementPosition(promptDisplay, paddingLeft, paddingTop);
+        }
+    }
+
+	/**
+	 *  @private
+	 */
+	override protected function measure():void
+	{
+		super.measure();
+		measureTextComponent(hostComponent);
+	}
+}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-examples/blob/539852e9/tourdeflexmobile/src/spark/skins/android4/StageTextInputSkin.as
----------------------------------------------------------------------
diff --git a/tourdeflexmobile/src/spark/skins/android4/StageTextInputSkin.as b/tourdeflexmobile/src/spark/skins/android4/StageTextInputSkin.as
new file mode 100644
index 0000000..4bcc4d9
--- /dev/null
+++ b/tourdeflexmobile/src/spark/skins/android4/StageTextInputSkin.as
@@ -0,0 +1,130 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.skins.android4
+{
+import spark.components.TextInput;
+import spark.components.supportClasses.StyleableTextField;
+import spark.skins.android4.supportClasses.StageTextSkinBase;
+
+/**
+ *  ActionScript-based skin for TextInput controls in mobile applications that uses a
+ *  StyleableStageText class for the text input. 
+ * 
+ *  @see spark.components.TextInput
+ *  @see spark.components.supportClasses.StyleableStageText
+ * 
+ *  @langversion 3.0
+ *  @playerversion AIR 3.0 
+ *  @productversion Flex 4.6
+ */
+public class StageTextInputSkin extends StageTextSkinBase
+{
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  Constructor.
+     *  
+     *  @langversion 3.0
+     *  @playerversion AIR 3.0
+     *  @productversion Flex 4.6
+     */
+    public function StageTextInputSkin()
+    {
+        super();
+        multiline = false;
+    }    
+
+    //--------------------------------------------------------------------------
+    //
+    //  Variables
+    //
+    //--------------------------------------------------------------------------
+    
+    /** 
+     *  @copy spark.skins.spark.ApplicationSkin#hostComponent
+     */
+    public var hostComponent:TextInput;  // SkinnableComponent will populate
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden methods
+    //
+    //--------------------------------------------------------------------------
+	
+	/**
+	 *  @private
+	 */	
+	override protected function measure():void
+	{
+		super.measure();
+		measureTextComponent(hostComponent);
+	}
+	
+    /**
+     *  @private
+     */
+    override protected function layoutContents(unscaledWidth:Number, 
+                                               unscaledHeight:Number):void
+    {
+        // base class handles border position & size
+        super.layoutContents(unscaledWidth, unscaledHeight);
+        
+        // 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 = Math.max(0, unscaledWidth - paddingLeft - paddingRight);
+        var unscaledTextHeight:Number = Math.max(0, unscaledHeight - paddingTop - paddingBottom);
+        
+        // default vertical positioning is centered
+        var textHeight:Number = getElementPreferredHeight(textDisplay);
+        var textY:Number = Math.round(0.5 * (unscaledTextHeight - textHeight)) + paddingTop;
+        
+        if (textDisplay)
+        {
+            textDisplay.commitStyles();
+            setElementSize(textDisplay, unscaledTextWidth, unscaledTextHeight);
+            setElementPosition(textDisplay, paddingLeft, textY);
+        }
+        
+        if (promptDisplay)
+        {
+            if (promptDisplay is StyleableTextField)
+                StyleableTextField(promptDisplay).commitStyles();
+            
+            var promptHeight:Number = getElementPreferredHeight(promptDisplay);
+            var promptY:Number = Math.round(0.5 * (unscaledTextHeight - promptHeight)) + paddingTop;
+                
+            setElementSize(promptDisplay, unscaledTextWidth, promptHeight);
+            setElementPosition(promptDisplay, paddingLeft, promptY);
+        }
+    }
+    
+    /**
+     *  @private
+     */
+}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-examples/blob/539852e9/tourdeflexmobile/src/spark/skins/android4/TabbedViewNavigatorTabBarSkin.as
----------------------------------------------------------------------
diff --git a/tourdeflexmobile/src/spark/skins/android4/TabbedViewNavigatorTabBarSkin.as b/tourdeflexmobile/src/spark/skins/android4/TabbedViewNavigatorTabBarSkin.as
new file mode 100644
index 0000000..eea5948
--- /dev/null
+++ b/tourdeflexmobile/src/spark/skins/android4/TabbedViewNavigatorTabBarSkin.as
@@ -0,0 +1,122 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.skins.android4
+{
+import spark.components.ButtonBarButton;
+import spark.components.DataGroup;
+import spark.skins.mobile.supportClasses.ButtonBarButtonClassFactory;
+import spark.skins.mobile.supportClasses.TabbedViewNavigatorTabBarHorizontalLayout;
+
+/**
+ *  The Android 4.x specific skin class for the Spark TabbedViewNavigator tabBar skin part.
+ *  It uses the ButtonBarFirstButtonSkin and ButtonBarMiddleButtonSkin as skins for first
+ *  middle buttons
+ *  
+ *  @see spark.components.TabbedViewNavigator#tabBar
+ *  
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 2.5
+ *  @productversion Flex 4.5
+ */
+public class TabbedViewNavigatorTabBarSkin extends ButtonBarSkin
+{
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  Constructor.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5 
+     *  @productversion Flex 4.5
+     * 
+     */
+    public function TabbedViewNavigatorTabBarSkin()
+    {
+        super();
+    }
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden methods
+    //
+    //--------------------------------------------------------------------------
+    
+    /**
+     *  @private
+     */
+    override protected function createChildren():void
+    {
+        if (!firstButton)
+        {
+            firstButton = new ButtonBarButtonClassFactory(ButtonBarButton);
+            firstButton.skinClass = spark.skins.android4.ButtonBarFirstButtonSkin;
+        }
+        
+        if (!lastButton)
+        {
+            lastButton = new ButtonBarButtonClassFactory(ButtonBarButton);
+            lastButton.skinClass = spark.skins.android4.ButtonBarFirstButtonSkin;
+        }
+        
+        if (!middleButton)
+        {
+            middleButton = new ButtonBarButtonClassFactory(ButtonBarButton);
+            middleButton.skinClass = spark.skins.android4.ButtonBarMiddleButtonSkin;
+        }
+        
+        if (!dataGroup)
+        {
+            // TabbedViewNavigatorButtonBarHorizontalLayout for even percent layout
+            var tabLayout:TabbedViewNavigatorTabBarHorizontalLayout = 
+                new TabbedViewNavigatorTabBarHorizontalLayout();
+            tabLayout.useVirtualLayout = false;
+            
+            dataGroup = new DataGroup();
+            dataGroup.layout = tabLayout;
+            addChild(dataGroup);
+        }
+    }
+    
+    /**
+     *  @private
+     */
+    override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+    {
+        super.drawBackground(unscaledWidth, unscaledHeight);
+
+        // backgroundAlpha style is not supported by ButtonBar
+        // TabbedViewNavigatorSkin sets a hard-coded value to support
+        // overlayControls
+        var backgroundAlphaValue:* = getStyle("backgroundAlpha");
+        var backgroundAlpha:Number = (backgroundAlphaValue === undefined)
+            ? 1 : getStyle("backgroundAlpha");
+        
+        graphics.beginFill(getStyle("chromeColor"), backgroundAlpha);
+        graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
+        graphics.endFill();
+    }
+}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-examples/blob/539852e9/tourdeflexmobile/src/spark/skins/android4/TextAreaHScrollBarSkin.as
----------------------------------------------------------------------
diff --git a/tourdeflexmobile/src/spark/skins/android4/TextAreaHScrollBarSkin.as b/tourdeflexmobile/src/spark/skins/android4/TextAreaHScrollBarSkin.as
new file mode 100644
index 0000000..540318e
--- /dev/null
+++ b/tourdeflexmobile/src/spark/skins/android4/TextAreaHScrollBarSkin.as
@@ -0,0 +1,105 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.skins.android4
+{
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+use namespace mx_internal;
+
+    /**
+     *  The default skin class for the Spark TextAreaHScrollBar component in mobile
+    *  applications.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5 
+     *  @productversion Flex 4.5
+     */
+public class TextAreaHScrollBarSkin extends HScrollBarSkin
+{
+    /**
+     *  Constructor.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5 
+     *  @productversion Flex 4.5
+     */
+    public function TextAreaHScrollBarSkin()
+    {
+        super();
+
+        thumbSkinClass = TextAreaHScrollBarThumbSkin;
+        var paddingBottom:int;
+        var paddingHorizontal:int;
+
+        switch (applicationDPI)
+        {
+			case DPIClassification.DPI_640:
+			{
+				minHeight = 30;
+				paddingBottom = TextAreaHScrollBarThumbSkin.PADDING_BOTTOM_320DPI;
+				paddingHorizontal = TextAreaHScrollBarThumbSkin.PADDING_HORIZONTAL_320DPI;
+				break;
+			}
+			case DPIClassification.DPI_480:
+			{
+				minHeight = 22;
+				paddingBottom = TextAreaHScrollBarThumbSkin.PADDING_BOTTOM_480DPI;
+				paddingHorizontal = TextAreaHScrollBarThumbSkin.PADDING_HORIZONTAL_480DPI;
+				break;
+			}
+            case DPIClassification.DPI_320:
+            {
+                minHeight = 15;
+                paddingBottom = TextAreaHScrollBarThumbSkin.PADDING_BOTTOM_320DPI;
+                paddingHorizontal = TextAreaHScrollBarThumbSkin.PADDING_HORIZONTAL_320DPI;
+                break;
+            }
+			case DPIClassification.DPI_240:
+			{
+				minHeight = 11;
+				paddingBottom = TextAreaHScrollBarThumbSkin.PADDING_BOTTOM_240DPI;
+				paddingHorizontal = TextAreaHScrollBarThumbSkin.PADDING_HORIZONTAL_240DPI;
+				break;
+			}
+			case DPIClassification.DPI_120:
+			{
+				minHeight = 11;
+				paddingBottom = TextAreaHScrollBarThumbSkin.PADDING_BOTTOM_120DPI;
+				paddingHorizontal = TextAreaHScrollBarThumbSkin.PADDING_HORIZONTAL_120DPI;
+				break;
+			}
+            default:
+            {
+                // default DPI_160
+                minHeight = 9;
+                paddingBottom = TextAreaHScrollBarThumbSkin.PADDING_BOTTOM_DEFAULTDPI;
+                paddingHorizontal = TextAreaHScrollBarThumbSkin.PADDING_HORIZONTAL_DEFAULTDPI;
+                break;
+            }
+        }
+        
+        // The minimum width is set such that, at it's smallest size, the thumb appears
+        // as wide as it is high.
+        minThumbWidth = (minHeight - paddingBottom) + (paddingHorizontal * 2);   
+    }
+}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-examples/blob/539852e9/tourdeflexmobile/src/spark/skins/android4/TextAreaHScrollBarThumbSkin.as
----------------------------------------------------------------------
diff --git a/tourdeflexmobile/src/spark/skins/android4/TextAreaHScrollBarThumbSkin.as b/tourdeflexmobile/src/spark/skins/android4/TextAreaHScrollBarThumbSkin.as
new file mode 100644
index 0000000..5d3fec8
--- /dev/null
+++ b/tourdeflexmobile/src/spark/skins/android4/TextAreaHScrollBarThumbSkin.as
@@ -0,0 +1,116 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.skins.android4
+{
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+use namespace mx_internal;
+
+/**
+ *  The ActionScript-based skin used for TextAreaHScrollBarThumb components
+ *  in mobile applications.
+ * 
+ *  @langversion 3.0
+ *  @playerversion AIR 2.5 
+ *  @productversion Flex 4.5
+ * 
+ */
+public class TextAreaHScrollBarThumbSkin extends HScrollBarThumbSkin
+{
+    //--------------------------------------------------------------------------
+    //
+    //  Class constants
+    //
+    //--------------------------------------------------------------------------
+    
+    // These constants are also accessed from HScrollBarSkin
+	mx_internal static const PADDING_BOTTOM_640DPI:int = 16;
+	mx_internal static const PADDING_HORIZONTAL_640DPI:int = 16;
+	mx_internal static const PADDING_BOTTOM_480DPI:int = 12;
+	mx_internal static const PADDING_HORIZONTAL_480DPI:int = 12;
+    mx_internal static const PADDING_BOTTOM_320DPI:int = 8;
+    mx_internal static const PADDING_HORIZONTAL_320DPI:int = 12;
+	mx_internal static const PADDING_BOTTOM_240DPI:int = 6;
+	mx_internal static const PADDING_HORIZONTAL_240DPI:int = 6;
+	mx_internal static const PADDING_BOTTOM_120DPI:int = 3;
+	mx_internal static const PADDING_HORIZONTAL_120DPI:int = 3;
+    mx_internal static const PADDING_BOTTOM_DEFAULTDPI:int = 4;
+    mx_internal static const PADDING_HORIZONTAL_DEFAULTDPI:int = 6;
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //--------------------------------------------------------------------------
+    /**
+     *  Constructor.
+     *  
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5
+     *  @productversion Flex 4.5
+     */
+    public function TextAreaHScrollBarThumbSkin()
+    {
+        super();
+        
+        // Depending on density set padding
+        switch (applicationDPI)
+        {
+			case DPIClassification.DPI_640:
+			{
+				paddingBottom = PADDING_BOTTOM_640DPI;
+				paddingHorizontal = PADDING_HORIZONTAL_640DPI;
+				break;
+			}
+			case DPIClassification.DPI_480:
+			{
+				paddingBottom = TextAreaHScrollBarThumbSkin.PADDING_BOTTOM_480DPI;
+				paddingHorizontal = TextAreaHScrollBarThumbSkin.PADDING_HORIZONTAL_480DPI;
+				break;
+			}
+            case DPIClassification.DPI_320:
+            {
+                paddingBottom = PADDING_BOTTOM_320DPI;
+                paddingHorizontal = PADDING_HORIZONTAL_320DPI;
+                break;
+            }
+			case DPIClassification.DPI_240:
+			{
+				paddingBottom = PADDING_BOTTOM_240DPI;
+				paddingHorizontal = PADDING_HORIZONTAL_240DPI;
+				break;
+			}
+			case DPIClassification.DPI_120:
+			{
+				paddingBottom = PADDING_BOTTOM_120DPI;
+				paddingHorizontal = PADDING_HORIZONTAL_120DPI;
+				break;
+			}
+            default:
+            {
+                paddingBottom = PADDING_BOTTOM_DEFAULTDPI;
+                paddingHorizontal = PADDING_HORIZONTAL_DEFAULTDPI;
+                break;
+            }
+        }
+    }
+}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-examples/blob/539852e9/tourdeflexmobile/src/spark/skins/android4/TextAreaSkin.as
----------------------------------------------------------------------
diff --git a/tourdeflexmobile/src/spark/skins/android4/TextAreaSkin.as b/tourdeflexmobile/src/spark/skins/android4/TextAreaSkin.as
new file mode 100644
index 0000000..6d1fa52
--- /dev/null
+++ b/tourdeflexmobile/src/spark/skins/android4/TextAreaSkin.as
@@ -0,0 +1,892 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.skins.android4
+{
+	
+	import flash.events.Event;
+	import flash.events.FocusEvent;
+	import flash.events.KeyboardEvent;
+	import flash.events.MouseEvent;
+	import flash.events.SoftKeyboardEvent;
+	import flash.geom.Point;
+	import flash.geom.Rectangle;
+	import flash.system.Capabilities;
+	import flash.text.TextLineMetrics;
+	import flash.ui.Keyboard;
+	
+	import mx.core.DPIClassification;
+	import mx.core.EventPriority;
+	import mx.core.FlexGlobals;
+	import mx.core.mx_internal;
+	import mx.events.FlexEvent;
+	import mx.utils.Platform;
+	
+	import spark.components.Group;
+	import spark.components.Scroller;
+	import spark.components.TextArea;
+	import spark.components.supportClasses.StyleableTextField;
+	import spark.events.CaretBoundsChangeEvent;
+	import spark.skins.android4.supportClasses.TextSkinBase;
+	
+	use namespace mx_internal;
+	
+	/**
+	 *  ActionScript-based skin for TextArea components in mobile applications.
+	 * 
+	 * @see spark.components.TextArea
+	 * 
+	 *  @langversion 3.0
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 2.5 
+	 *  @productversion Flex 4.5
+	 */
+	public class TextAreaSkin extends TextSkinBase 
+	{
+		/**
+		 *  @private
+		 *  Right-margin of iOS native text control when editing on a retina display
+		 *  based on fontSize 32.
+		 */
+		mx_internal static var IOS_RIGHT_MARGIN_320:Number = 19;
+		
+		/**
+		 *  @private
+		 *  Right-margin of iOS native text control when editing on a retina display
+		 *  based on fontSize 16 scaling from applicationDPI 160.
+		 */
+		mx_internal static var IOS_RIGHT_MARGIN_160_SCALED_TO_320:Number = 9.4;
+		
+		/**
+		 *  @private
+		 *  Right-margin of iOS native text control when editing on a standard display
+		 *  based on fontSize 16 and runtimeDPI 160.
+		 */
+		mx_internal static var IOS_RIGHT_MARGIN_160:Number = 20.6;
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Constructor
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  Constructor.
+		 *  
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5
+		 *  @productversion Flex 4.5
+		 */
+		public function TextAreaSkin()
+		{
+			super();
+			
+			addEventListener(Event.RESIZE, resizeHandler);
+			
+			switch (applicationDPI)
+			{
+				case DPIClassification.DPI_640:
+				{
+					measuredDefaultWidth = 1024;
+					measuredDefaultHeight = 212;
+					layoutBorderSize = 4;
+					flatheight = 9;
+					break;
+				}
+				case DPIClassification.DPI_480:
+				{
+					measuredDefaultWidth = 880;
+					measuredDefaultHeight = 140;
+					layoutBorderSize = 3;
+					flatheight = 7;	
+					break;
+				}
+				case DPIClassification.DPI_320:
+				{
+					measuredDefaultWidth = 612;
+					measuredDefaultHeight = 106;
+					layoutBorderSize = 2;
+					flatheight = 6;		
+					break;
+				}
+				case DPIClassification.DPI_240:
+				{
+					measuredDefaultWidth = 440;
+					measuredDefaultHeight = 70;
+					layoutBorderSize = 2;
+					flatheight = 5;
+					break;
+				}
+				case DPIClassification.DPI_120:
+				{
+					measuredDefaultWidth = 220;
+					measuredDefaultHeight = 35;
+					layoutBorderSize = 1;
+					flatheight = 2;
+					break;
+				}
+				default:
+				{
+					measuredDefaultWidth = 306;
+					measuredDefaultHeight = 53;
+					layoutBorderSize = 1;
+					flatheight = 3; 
+					break;
+				}
+			}
+			addEventListener(FocusEvent.FOCUS_IN, focusChangeHandler);
+			addEventListener(FocusEvent.FOCUS_OUT, focusChangeHandler);
+		}
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Skin parts
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  Scroller skin part.
+		 *
+		 *  @langversion 3.0
+		 *  @playerversion Flash 10
+		 *  @playerversion AIR 2.5 
+		 *  @productversion Flex 4.5
+		 */ 
+		public var scroller:Scroller;
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Properties
+		//
+		//--------------------------------------------------------------------------
+		
+		/** 
+		 *  @copy spark.skins.spark.ApplicationSkin#hostComponent
+		 */
+		public var hostComponent:TextArea;
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Variables
+		//
+		//--------------------------------------------------------------------------
+		
+		protected var isFocused:Boolean = false;
+		
+		protected var flatheight:uint;
+		
+		/**
+		 *  @private
+		 *  The width of the component on the previous layout manager 
+		 *  pass.  This gets set in updateDisplayList() and used in measure() on 
+		 *  the next layout pass.  This is so our "guessed width" in measure() 
+		 *  will be as accurate as possible since textDisplay is multiline and 
+		 *  the textDisplay height is dependent on the width.
+		 * 
+		 *  In the constructor this is actually set based on the DPI.
+		 */
+		mx_internal var oldUnscaledWidth:Number;
+		
+		private var textDisplayGroup:Group;
+		private var _isIOS:Boolean;
+		private var invalidateCaretPosition:Boolean = true;
+		private var oldCaretBounds:Rectangle = new Rectangle(-1, -1, -1, -1);
+		private var lastTextHeight:Number;
+		private var lastTextWidth:Number;
+		
+		private var isTextDisplayTall:Boolean = true;
+		private var growTextDisplay:Boolean = false;
+		private var shrinkTextDisplay:Boolean = false;
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Overridden methods
+		//
+		//--------------------------------------------------------------------------
+		
+		/**
+		 *  @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.lineBreak = getStyle("lineBreak");
+				textDisplay.useTightTextBounds = false;
+				textDisplay.scrollToRangeDelegate = scrollToRange;
+				
+				// on iOS, resize the TextField and let the native control handle scrolling
+				_isIOS = Platform.isIOS;
+				
+				if (_isIOS)
+				{
+					// hard-coded rightMargin for iOS native text control
+					// this value is independent of the paddingRight style
+					var rightMargin:Number = 0;
+					var isRetina:Boolean = false;
+					var isScaling160to320:Boolean = false;
+					
+					// check for scaling
+					if ("runtimeDPI" in FlexGlobals.topLevelApplication)
+					{
+						var runtimeDPI:Number = FlexGlobals.topLevelApplication.runtimeDPI as Number;
+						isRetina = (runtimeDPI == DPIClassification.DPI_320);
+						isScaling160to320 = isRetina
+							&& (applicationDPI == DPIClassification.DPI_160);
+					}
+					
+					if (isRetina && !isScaling160to320)
+						rightMargin = IOS_RIGHT_MARGIN_320;
+					else if (isRetina && isScaling160to320)
+						rightMargin = IOS_RIGHT_MARGIN_160_SCALED_TO_320;
+					else
+						rightMargin = IOS_RIGHT_MARGIN_160;
+					
+					textDisplay.rightMargin = rightMargin;
+				}
+				else
+				{
+					textDisplay.addEventListener(KeyboardEvent.KEY_DOWN, textDisplay_keyHandler);
+				}
+				
+				textDisplay.addEventListener(Event.CHANGE, textDisplay_changeHandler);
+				textDisplay.addEventListener(FlexEvent.VALUE_COMMIT, textDisplay_changeHandler);
+				textDisplay.addEventListener(Event.SCROLL, textDisplay_scrollHandler);
+				// Use a lower priority so that the StyleableTextField event handler is called first. 
+				// That handler cancels the event and we need to check for that case
+				textDisplay.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATING, textDisplay_softKeyboardActivatingHandler, false, EventPriority.DEFAULT_HANDLER);
+				textDisplay.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE, textDisplay_softKeyboardActivateHandler);
+				textDisplay.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, textDisplay_softKeyboardDeactivateHandler);
+				
+				textDisplay.left = getStyle("paddingLeft");
+				textDisplay.top = getStyle("paddingTop");
+				textDisplay.right = getStyle("paddingRight");
+				textDisplay.bottom = getStyle("paddingBottom");
+				
+				// wrap StyleableTextComponent in Group for viewport
+				textDisplayGroup = new Group();
+				textDisplayGroup.clipAndEnableScrolling = true;
+				textDisplayGroup.addElement(textDisplay);
+			}
+			
+			if (!scroller)
+			{
+				scroller = new Scroller();
+				scroller.minViewportInset = 0;
+				scroller.measuredSizeIncludesScrollBars = false;
+				scroller.ensureElementIsVisibleForSoftKeyboard = false;
+				
+				addChild(scroller);
+			}
+			
+			if (!scroller.viewport)
+				scroller.viewport = textDisplayGroup;
+			
+			super.createChildren();
+		}
+		
+		/**
+		 *  @private
+		 *  TextArea prompt supports wrapping and multiline
+		 */
+		override protected function createPromptDisplay():StyleableTextField
+		{
+			var prompt:StyleableTextField = super.createPromptDisplay();
+			prompt.editable = true;
+			prompt.wordWrap = true;
+			
+			return prompt;
+		}
+		
+		/**
+		 *  @private
+		 */
+		override protected function measure():void
+		{
+			super.measure();
+			
+			var paddingTop:Number = getStyle("paddingTop");
+			var paddingBottom:Number = getStyle("paddingBottom");
+			var paddingLeft:Number = getStyle("paddingLeft");
+			var paddingRight:Number = getStyle("paddingRight");
+			
+			// TextDisplay always defaults to 440 pixels wide (the value is DPI dependent), 
+			// and tall enough to show all text.
+			// 
+			// You can set an explicit width and the height will adjust accordingly. The opposite
+			// is not true: setting an explicit height will not adjust the width accordingly.
+			
+			measuredWidth = measuredDefaultWidth;
+			
+			// now we need to measure textDisplay's height.  Unfortunately, this is tricky and 
+			// is dependent on textDisplay's width.  Let's use the heuristic that our width 
+			// is the same as our last width.
+			// We don't use layoutMeasuredWidth, because that value is just a constant and doesn't
+			// take into account the fact that the TextArea could have an explicitWidth or could 
+			// be constrained by some value.  However, we still default oldTextDisplayWidth to 
+			// be layoutMeasuredWidth the first time through.
+			var textDisplayEstimatedWidth:Number = oldUnscaledWidth - paddingLeft - paddingRight;
+			
+			// now we need to measure textDisplay's height.  Unfortunately, this is tricky and 
+			// is dependent on textDisplay's width.  
+			// Use the old textDisplay width as an estimte for the new one.  
+			// If we are wrong, we'll find out in updateDisplayList()
+			textDisplay.commitStyles();
+			
+			// Clear min sizes first.
+			textDisplay.minWidth = textDisplay.minHeight = NaN;
+			
+			// If lineBreak == explicit, always use NaN for estimated width
+			if (getStyle("lineBreak") == "explicit")
+				textDisplayEstimatedWidth = NaN;
+			
+			setElementSize(textDisplay, textDisplayEstimatedWidth, NaN);
+			
+			measuredHeight = getElementPreferredHeight(textDisplay) + paddingTop + 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);
+			}
+			
+			setElementSize(scroller, unscaledWidth, unscaledHeight);
+			setElementPosition(scroller, 0, 0);
+			
+			// position & size the text
+			var explicitLineBreak:Boolean = getStyle("lineBreak") == "explicit";
+			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;
+			var textHeight:Number;
+			var textWidth:Number = explicitLineBreak ? textDisplay.measuredTextSize.x : unscaledTextWidth;
+			
+			var lineIndex:int;
+			var topCharIndex:int;
+			var charBounds:Rectangle;
+			
+			// grab old measured textDisplay height before resizing it
+			var oldPreferredTextHeight:Number = getElementPreferredHeight(textDisplay);
+			
+			// set width first to measure height correctly
+			textDisplay.commitStyles();
+			textDisplay.setLayoutBoundsSize(textWidth, NaN);
+			
+			// In iOS, when we go into editing mode, the runtime overlays a native 
+			// text control over the textDisplay. In order to prevent the text 
+			// from overflowing the component and to get scrolling support, the 
+			// native text control must be the same size as the TextArea
+			if (_isIOS)
+			{
+				if (shrinkTextDisplay)
+				{
+					// Switching to edit mode. Convert from viewport scrolling to 
+					// TextField scrolling
+					var vsp:Number = textDisplayGroup.verticalScrollPosition;
+					
+					var lineMetrics:TextLineMetrics = textDisplay.getLineMetrics(0);
+					var lineHeight:Number = lineMetrics.ascent + lineMetrics.descent;
+					
+					// TODO Figure out how to get the x offset. Right now is hard coded to 2
+					// At least half the line should be showing before we scroll to that line
+					// This makes the conversion from pixel to line based scrolling a little less jumpy
+					lineIndex = textDisplay.getLineIndexAtPoint(2, vsp + lineHeight / 2) + 1;
+					textDisplayGroup.verticalScrollPosition = 0;
+					isTextDisplayTall = false;
+					//trace("TAS.layoutContents shrinkText vsp",vsp,"lineIndex",lineIndex);
+				}
+					
+				else if (growTextDisplay)
+				{
+					// Leaving edit mode. Convert from TextField scrolling to 
+					// viewport scrolling
+					var scrollV:Number = textDisplay.scrollV;
+					
+					// TODO (jszeto) investigate using lineMetrics.lineHeight * scrollV instead of getCharBoundaries
+					topCharIndex = textDisplay.getLineOffset(scrollV - 1);
+					charBounds = textDisplay.getCharBoundaries(topCharIndex);
+					// If the charBounds is null, just set vsp to 0
+					if (charBounds == null)
+						charBounds = new Rectangle(0, 0, 0, 0);
+					textDisplay.scrollV = 1;
+					isTextDisplayTall = true;
+					//trace("TAS.layoutContents growText scrollV",scrollV,"topCharIndex",topCharIndex,"charBounds",charBounds);
+				}
+			}
+			
+			// TextField height should match its content or the TextArea bounds at minimum
+			// iOS special case to prevent Flex Scroller scrolling when editable
+			if (isTextDisplayTall)
+				textHeight = Math.max(textDisplay.measuredTextSize.y, unscaledTextHeight);
+			else
+				textHeight = unscaledTextHeight;
+			
+			// FIXME (jasonsj): iOS native scroll bar appears even when explictHeight
+			//                  is not specified. Focus-in is jumpy.
+			
+			if (promptDisplay)
+			{
+				promptDisplay.commitStyles();
+				setElementSize(promptDisplay, unscaledTextWidth, textHeight);
+				setElementPosition(promptDisplay, paddingLeft, paddingTop);
+				
+				// no need to update textDisplay if promptDisplay is present
+				return;
+			}
+			
+			// keep track of oldUnscaledWidth so we have a good guess as to the width 
+			// of the textDisplay on the next measure() pass
+			oldUnscaledWidth = unscaledWidth;
+			
+			// set the width of textDisplay to textWidth.
+			// set the height to oldTextHeight.  If the height's actually wrong, 
+			// we'll invalidateSize() and go through this layout pass again anyways
+			setElementSize(textDisplay, textWidth, textHeight);
+			
+			// Set minWidth/Height on the text so the textDisplayGroup sizes accordingly
+			textDisplay.minWidth = textWidth;
+			textDisplay.minHeight = textHeight;
+			textDisplayGroup.invalidateDisplayList();
+			
+			// grab new measured textDisplay height after the textDisplay has taken its final width
+			var newPreferredTextHeight:Number = getElementPreferredHeight(textDisplay);
+			
+			// if the resize caused the textDisplay's height to change (because of 
+			// text reflow), then we need to remeasure ourselves with our new width
+			if (oldPreferredTextHeight != newPreferredTextHeight)
+				invalidateSize();
+			
+			if (_isIOS)
+			{
+				if (shrinkTextDisplay)
+				{
+					scroller.validateNow();
+					textDisplay.scrollV = lineIndex;
+				}
+				else if (growTextDisplay)
+				{
+					scroller.validateNow();
+					textDisplayGroup.verticalScrollPosition = charBounds.y;
+				}               
+				
+				shrinkTextDisplay = false;
+				growTextDisplay = false;
+			}
+			
+			//trace("TAS.layoutContents tH",textHeight,"tW",textWidth,"invalidateCaret",invalidateCaretPosition);
+			
+			// checking if text fits in TextArea
+			// does not apply to iOS due to native text editing and scrolling
+			// invalidateCaretPosition will never be true for iOS
+			if (invalidateCaretPosition && isTextDisplayTall)
+			{
+				// if the caret is outside the viewport, update the Group verticalScrollPosition
+				var charIndex:int = textDisplay.selectionBeginIndex;
+				var caretBounds:Rectangle = textDisplay.getCharBoundaries(charIndex);
+				lineIndex = textDisplay.getLineIndexOfChar(charIndex);
+				
+				// getCharBoundaries() returns null for new lines
+				if (!caretBounds)
+				{
+					// temporarily insert a character at the caretIndex
+					textDisplay.replaceText(charIndex, charIndex, "W");
+					caretBounds = textDisplay.getCharBoundaries(charIndex);
+					lineIndex = textDisplay.getLineIndexOfChar(charIndex);
+					textDisplay.replaceText(charIndex, charIndex + 1, "");   
+				}
+				
+				if (caretBounds)
+				{
+					// Scroll the internal Scroller to ensure the caret is visible
+					if (textHeight > unscaledTextHeight)
+					{
+						
+						if (charIndex == textDisplay.text.length)
+						{
+							// Make sure textDisplayGroup is validated, otherwise the 
+							// verticalScrollPosition may be out of bounds, which will
+							// cause a bounce effect.
+							textDisplayGroup.validateNow();
+							textDisplayGroup.verticalScrollPosition = textHeight;
+						}
+						else
+						{
+							// caretTopPositon and caretBottomPosition are TextField-relative positions
+							// the TextField is inset by padding styles of the TextArea (via the VGroup)
+							
+							// adjust top position to 0 when on the first line
+							// caretTopPosition will be negative when off stage
+							var caretTopPosition:Number = ((caretBounds.y) < 0 || (lineIndex == 0))
+								? 0 : caretBounds.y;
+							
+							// caretBottomPosition is the y coordinate of the bottom bounds of the caret
+							var caretBottomPosition:Number = caretBounds.y + caretBounds.height;
+							
+							// note that verticalScrollPosition min/max do not account for padding
+							var vspTop:Number = textDisplayGroup.verticalScrollPosition;
+							
+							// vspBottom should be the max visible Y in the TextField
+							// coordinate space.
+							// remove paddingBottom for some clearance between caret and border
+							var vspBottom:Number = vspTop + unscaledHeight - paddingTop - paddingBottom;
+							
+							// is the caret in or below the padding and viewport?
+							if (caretBottomPosition > vspBottom)
+							{
+								// adjust caretBottomPosition to max scroll position when on the last line
+								if (lineIndex + 1 == textDisplay.numLines)
+								{
+									// use textHeight+paddings instead of textDisplayGroup.contentHeight
+									// Group has not been resized by this point
+									textDisplayGroup.verticalScrollPosition = (textHeight + paddingTop + paddingBottom) - textDisplayGroup.height;
+								}
+								else
+								{
+									// bottom edge of the caret moves just inside the bottom edge of the scroller
+									// add delta between caret and vspBottom
+									textDisplayGroup.verticalScrollPosition = vspTop + (caretBottomPosition - vspBottom);
+								}
+							}
+								// is the caret above the viewport?
+							else if (caretTopPosition < vspTop)
+							{
+								// top edge of the caret moves inside the top edge of the scroller
+								textDisplayGroup.verticalScrollPosition = caretTopPosition;
+							}
+						}
+						
+						scroller.validateNow();
+					}
+					
+					// Convert to local coordinates
+					// Dispatch an event for an ancestor Scroller
+					// It will scroll the TextArea so the caret is in view
+					convertBoundsToLocal(caretBounds);
+					if (oldCaretBounds == null || caretBounds.bottom != oldCaretBounds.bottom || caretBounds.top != oldCaretBounds.top)
+					{
+						//trace("TAS.layoutContents send caret CHANGE");
+						dispatchEvent(new CaretBoundsChangeEvent(CaretBoundsChangeEvent.CARET_BOUNDS_CHANGE,true,true,oldCaretBounds,caretBounds));
+					}
+					
+					oldCaretBounds = caretBounds;   
+				}
+				
+				invalidateCaretPosition = false;
+			}
+			
+			// Make sure final scroll position is valid
+			if (isTextDisplayTall)
+				snapTextScrollPosition();
+		}
+		
+		override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+		{
+			super.drawBackground(unscaledWidth, unscaledHeight);
+			
+			var contentBackgroundColor:uint = getStyle("contentBackgroundColor");
+			var contentBackgroundAlpha:Number = getStyle("contentBackgroundAlpha");	
+			//change border color and thickness when in focus
+			var borderColor:uint = isFocused ? getStyle("focusColor") : getStyle("borderColor");
+			var selectWidth:uint = isFocused ? layoutBorderSize + 1 : layoutBorderSize;
+			if (isNaN(contentBackgroundAlpha))
+			{
+				contentBackgroundAlpha = 1;
+			}        
+			if (getStyle("contentBackgroundBorder") == "flat")
+			{		
+				var halfGap:int = flatheight * 2;
+				//background
+				graphics.beginFill(contentBackgroundColor, contentBackgroundAlpha);
+				graphics.drawRect(0, 0, unscaledWidth, unscaledHeight - flatheight);
+				graphics.endFill();
+				//begin flat border
+				graphics.beginFill(borderColor, 1);
+				//left half border
+				graphics.drawRect(0, unscaledHeight - halfGap, selectWidth, flatheight );
+				//bottom border
+				graphics.drawRect(0, unscaledHeight - flatheight, unscaledWidth, selectWidth);
+				//right border
+				graphics.drawRect(unscaledWidth - selectWidth, unscaledHeight - halfGap, selectWidth, flatheight);
+				graphics.endFill();
+			}
+			else if (getStyle("contentBackgroundBorder") == "rectangle")
+			{
+				var borderWidth:uint = layoutBorderSize * 2;
+				//rectangle border and background
+				graphics.lineStyle(selectWidth, borderColor, 1);
+				graphics.beginFill(contentBackgroundColor, contentBackgroundAlpha);
+				graphics.drawRect(layoutBorderSize, layoutBorderSize, unscaledWidth - borderWidth, unscaledHeight - borderWidth);
+				graphics.endFill();
+			}
+		}
+		
+		/**
+		 *  @private
+		 *  Make sure the scroll positions are valid, and adjust if needed.
+		 */
+		private function snapTextScrollPosition():void
+		{
+			var maxHsp:Number = textDisplayGroup.contentWidth > textDisplayGroup.width ? 
+				textDisplayGroup.contentWidth-textDisplayGroup.width : 0; 
+			textDisplayGroup.horizontalScrollPosition = 
+				Math.min(Math.max(0,textDisplayGroup.horizontalScrollPosition),maxHsp);
+			
+			var maxVsp:Number = textDisplayGroup.contentHeight > textDisplayGroup.height ? 
+				textDisplayGroup.contentHeight-textDisplayGroup.height : 0; 
+			
+			textDisplayGroup.verticalScrollPosition = 
+				Math.min(Math.max(0,textDisplayGroup.verticalScrollPosition),maxVsp);
+		}
+		
+		/**
+		 *  @private
+		 *  Get the bounds of the caret
+		 */    
+		private function getCaretBounds():Rectangle
+		{
+			var charIndex:int = textDisplay.selectionBeginIndex;
+			var caretBounds:Rectangle = textDisplay.getCharBoundaries(charIndex);
+			
+			if (!caretBounds)
+			{
+				textDisplay.replaceText(charIndex, charIndex, "W");
+				caretBounds = textDisplay.getCharBoundaries(charIndex);
+				textDisplay.replaceText(charIndex, charIndex + 1, "");
+			}
+			
+			return caretBounds;
+		}
+		
+		/**
+		 *  @private
+		 *  Convert bounds from textDisplay to local coordinates
+		 */
+		private function convertBoundsToLocal(bounds:Rectangle):void
+		{
+			if (bounds)
+			{
+				var position:Point = new Point(bounds.x, bounds.y);
+				position = textDisplay.localToGlobal(position);
+				position = globalToLocal(position);
+				bounds.x = position.x;
+				bounds.y = position.y;
+			}
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function scrollToRange(anchorPosition:int, activePosition:int):void
+		{
+			var pos:int = Math.min(anchorPosition, activePosition);
+			var bounds:Rectangle = textDisplay.getCharBoundaries(pos);
+			var vsp:int = textDisplayGroup.verticalScrollPosition;
+			var paddingTop:Number = getStyle("paddingTop");
+			var paddingBottom:Number = getStyle("paddingBottom");
+			
+			if (bounds && (bounds.top < vsp - paddingTop || 
+				bounds.bottom > vsp + unscaledHeight - paddingTop - paddingBottom))
+			{
+				textDisplayGroup.verticalScrollPosition = bounds.top + paddingTop;
+				snapTextScrollPosition();
+			}
+		}
+		
+		/**
+		 *  @private
+		 *  Handle size and caret position changes that occur when text content
+		 *  changes.
+		 */
+		private function textDisplay_changeHandler(event:Event):void
+		{
+			var tH:Number = textDisplay.textHeight;
+			var tW:Number = textDisplay.textWidth;
+			var explicitLineBreak:Boolean = getStyle("lineBreak") == "explicit";
+			
+			// Size and caret position have changed if the text height is different or
+			// the text width is different and we aren't word wrapping
+			if (tH != lastTextHeight || ( explicitLineBreak && tW != lastTextWidth))
+			{
+				invalidateSize();
+				invalidateDisplayList();
+				invalidateCaretPosition = true;   
+			}
+			
+			lastTextHeight = tH;
+			lastTextWidth = tW;
+		}
+		
+		/**
+		 *  @private
+		 *  Cancels any native scroll that the Flash Player attempts to do
+		 */
+		private function textDisplay_scrollHandler(event:Event):void
+		{
+			// if iOS, let the OS handle scrolling
+			if (_isIOS)
+				return;
+			
+			// If not IOS, we will handle scrolling, so don't let the native
+			// flash textfield scroll at all.
+			if (textDisplay.scrollV > 1)
+				textDisplay.scrollV = 1;
+			if (textDisplay.scrollH > 0)
+				textDisplay.scrollH = 0;
+		}
+		
+		/**
+		 *  @private
+		 *  Adjust viewport when using key navigation
+		 */
+		private function textDisplay_keyHandler(event:KeyboardEvent):void
+		{
+			// update scroll position when caret changes
+			if ((event.keyCode == Keyboard.UP
+				|| event.keyCode == Keyboard.DOWN
+				|| event.keyCode == Keyboard.LEFT
+				|| event.keyCode == Keyboard.RIGHT))
+			{
+				invalidateDisplayList();
+				invalidateCaretPosition = true;
+			}
+			
+			// Change event is not always sent when delete key is pressed, so
+			// invalidate the size here
+			if (event.keyCode == Keyboard.BACKSPACE)
+			{
+				invalidateSize();
+			}
+		}
+		
+		/**
+		 *  @private
+		 *  When entering edit mode on iOS, we need to shrink the textDisplay to 
+		 *  the size of the TextArea  
+		 */ 
+		private function textDisplay_softKeyboardActivatingHandler(event:SoftKeyboardEvent):void
+		{
+			if (event.isDefaultPrevented())
+				return;
+			
+			if (_isIOS && isTextDisplayTall)
+			{
+				//trace("TAS.SK ACTIVATING targ",event.target);
+				shrinkTextDisplay = true;
+				invalidateDisplayList();
+				validateNow();
+			}
+		}  
+		
+		/**
+		 *  @private
+		 *  Send a caret change event to an ancestor Scroller
+		 */
+		private function textDisplay_softKeyboardActivateHandler(event:SoftKeyboardEvent):void
+		{
+			var keyboardRect:Rectangle = stage.softKeyboardRect;
+			
+			if (keyboardRect.width > 0 && keyboardRect.height > 0)
+			{
+				var newCaretBounds:Rectangle = getCaretBounds();
+				convertBoundsToLocal(newCaretBounds);
+				
+				if (oldCaretBounds != newCaretBounds)
+				{
+					//trace("TAS.SK ACTIVATE",keyboardRect,"dispatch caret CHANGE","newCaretBounds",newCaretBounds);
+					dispatchEvent(new CaretBoundsChangeEvent(CaretBoundsChangeEvent.CARET_BOUNDS_CHANGE,true,true,oldCaretBounds,newCaretBounds));
+					oldCaretBounds = newCaretBounds;
+				}
+			}
+		}
+		
+		/**
+		 *  @private
+		 *  On iOS, when leaving edit mode, we need to restore the textDisplay to the
+		 *  height of the text.
+		 */  
+		private function textDisplay_softKeyboardDeactivateHandler(event:SoftKeyboardEvent):void
+		{
+			if (_isIOS && !isTextDisplayTall)
+			{
+				growTextDisplay = true;
+				invalidateDisplayList();
+			}
+		}
+		
+		/**
+		 *  @private
+		 */
+		private function resizeHandler(event:Event):void
+		{
+			// Resizing needs to tickle the TextArea's internal auto-scroll logic
+			invalidateCaretPosition = true;
+			invalidateDisplayList();
+		}
+		
+		/**
+		 *  @private
+		 */
+		override public function styleChanged(styleProp:String):void
+		{
+			super.styleChanged(styleProp);
+			
+			// propogate styleChanged explicitly to textDisplay
+			if (textDisplay)
+				textDisplay.styleChanged(styleProp);
+			
+			// Check for padding style changes
+			if (!styleProp || styleProp == "styleName" || styleProp.indexOf("padding") >= 0)
+			{
+				if (textDisplay)
+				{
+					textDisplay.left = getStyle("paddingLeft");
+					textDisplay.top = getStyle("paddingTop");
+					textDisplay.right = getStyle("paddingRight");
+					textDisplay.bottom = getStyle("paddingBottom");
+				}
+			}
+		}
+		
+		private function focusChangeHandler(event:FocusEvent):void
+		{
+			isFocused = event.type == FocusEvent.FOCUS_IN;
+			invalidateDisplayList();		
+		}
+		
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-examples/blob/539852e9/tourdeflexmobile/src/spark/skins/android4/TextAreaVScrollBarSkin.as
----------------------------------------------------------------------
diff --git a/tourdeflexmobile/src/spark/skins/android4/TextAreaVScrollBarSkin.as b/tourdeflexmobile/src/spark/skins/android4/TextAreaVScrollBarSkin.as
new file mode 100644
index 0000000..f65b679
--- /dev/null
+++ b/tourdeflexmobile/src/spark/skins/android4/TextAreaVScrollBarSkin.as
@@ -0,0 +1,105 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.skins.android4
+{
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+use namespace mx_internal;
+
+/**
+ *  ActionScript-based skin for TextAreaVScrollBar components in mobile applications.
+ * 
+ *  @langversion 3.0
+ *  @playerversion Flash 10.1
+ *  @playerversion AIR 2.5 
+ *  @productversion Flex 4.5
+ */
+public class TextAreaVScrollBarSkin extends VScrollBarSkin
+{
+    /**
+     *  Constructor. 
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5 
+     *  @productversion Flex 4.5
+     * 
+     */ 
+    public function TextAreaVScrollBarSkin()
+    {
+        super();
+
+        thumbSkinClass = TextAreaVScrollBarThumbSkin;
+        var paddingRight:int;
+        var paddingVertical:int;
+
+        switch (applicationDPI)
+        {
+			case DPIClassification.DPI_640:
+			{
+				minWidth = 30;
+				paddingRight = TextAreaVScrollBarThumbSkin.PADDING_RIGHT_640DPI;
+				paddingVertical = TextAreaVScrollBarThumbSkin.PADDING_VERTICAL_640DPI;
+				break;
+			}
+			case DPIClassification.DPI_480:
+			{
+				minWidth = 22;
+				paddingRight = TextAreaVScrollBarThumbSkin.PADDING_RIGHT_480DPI;
+				paddingVertical = TextAreaVScrollBarThumbSkin.PADDING_VERTICAL_480DPI;
+				break;
+			}
+            case DPIClassification.DPI_320:
+            {
+                minWidth = 15;
+                paddingRight = TextAreaVScrollBarThumbSkin.PADDING_RIGHT_320DPI;
+                paddingVertical = TextAreaVScrollBarThumbSkin.PADDING_VERTICAL_320DPI;
+                break;
+            }
+			case DPIClassification.DPI_240:
+			{
+				minWidth = 11;
+				paddingRight = TextAreaVScrollBarThumbSkin.PADDING_RIGHT_240DPI;
+				paddingVertical = TextAreaVScrollBarThumbSkin.PADDING_VERTICAL_240DPI;
+				break;
+			}
+			case DPIClassification.DPI_120:
+			{
+				minWidth = 6;
+				paddingRight = TextAreaVScrollBarThumbSkin.PADDING_RIGHT_120DPI;
+				paddingVertical = TextAreaVScrollBarThumbSkin.PADDING_VERTICAL_120DPI;
+				break;
+			}
+            default:
+            {
+                // default DPI_160
+                minWidth = 9;
+                paddingRight = TextAreaVScrollBarThumbSkin.PADDING_RIGHT_DEFAULTDPI;
+                paddingVertical = TextAreaVScrollBarThumbSkin.PADDING_VERTICAL_DEFAULTDPI;
+                break;
+            }
+        }
+        
+        // The minimum height is set such that, at it's smallest size, the thumb appears
+        // as high as it is wide.
+        minThumbHeight = (minWidth - paddingRight) + (paddingVertical * 2);  
+    }
+}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-examples/blob/539852e9/tourdeflexmobile/src/spark/skins/android4/TextAreaVScrollBarThumbSkin.as
----------------------------------------------------------------------
diff --git a/tourdeflexmobile/src/spark/skins/android4/TextAreaVScrollBarThumbSkin.as b/tourdeflexmobile/src/spark/skins/android4/TextAreaVScrollBarThumbSkin.as
new file mode 100644
index 0000000..5cc1ea0
--- /dev/null
+++ b/tourdeflexmobile/src/spark/skins/android4/TextAreaVScrollBarThumbSkin.as
@@ -0,0 +1,117 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.skins.android4
+{
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+use namespace mx_internal;
+
+/**
+ *  The ActionScript-based skin used for TextAreaHScrollBarThumb components
+ *  in mobile applications.
+ * 
+ *  @langversion 3.0
+ *  @playerversion AIR 2.5 
+ *  @productversion Flex 4.5
+ * 
+ */
+public class TextAreaVScrollBarThumbSkin extends VScrollBarThumbSkin
+{
+    //--------------------------------------------------------------------------
+    //
+    //  Class constants
+    //
+    //--------------------------------------------------------------------------
+    
+    // These constants are also accessed from TextAreaVScrollBarSkin
+	mx_internal static const PADDING_RIGHT_640DPI:int = 16;
+	mx_internal static const PADDING_VERTICAL_640DPI:int = 24;
+	mx_internal static const PADDING_RIGHT_480DPI:int = 12;
+	mx_internal static const PADDING_VERTICAL_480DPI:int = 18;
+	mx_internal static const PADDING_RIGHT_320DPI:int = 8;
+    mx_internal static const PADDING_VERTICAL_320DPI:int = 12;
+	mx_internal static const PADDING_RIGHT_240DPI:int = 4;
+	mx_internal static const PADDING_VERTICAL_240DPI:int = 6;
+	mx_internal static const PADDING_RIGHT_120DPI:int = 2;
+	mx_internal static const PADDING_VERTICAL_120DPI:int = 3;
+    mx_internal static const PADDING_RIGHT_DEFAULTDPI:int = 4;
+    mx_internal static const PADDING_VERTICAL_DEFAULTDPI:int = 6;
+    
+    //--------------------------------------------------------------------------
+    //
+    //  Constructor
+    //
+    //-------------------------------------------------------------------------- 
+    /**
+     *  Constructor.
+     * 
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 2.5 
+     *  @productversion Flex 4.5
+     * 
+     */
+    public function TextAreaVScrollBarThumbSkin()
+    {
+        super();
+        
+        // Depending on density set padding
+        switch (applicationDPI)
+        {
+			case DPIClassification.DPI_640:
+			{
+				paddingRight = PADDING_RIGHT_640DPI;
+				paddingVertical = PADDING_VERTICAL_640DPI;
+				break;
+			}
+			case DPIClassification.DPI_480:
+			{
+				paddingRight = PADDING_RIGHT_480DPI;
+				paddingVertical = PADDING_VERTICAL_480DPI;
+				break;
+			}		
+            case DPIClassification.DPI_320:
+            {
+                paddingRight = PADDING_RIGHT_320DPI;
+                paddingVertical = PADDING_VERTICAL_320DPI;
+                break;
+            }
+			case DPIClassification.DPI_240:
+			{
+				paddingRight = PADDING_RIGHT_240DPI;
+				paddingVertical = PADDING_VERTICAL_240DPI;
+				break;
+			}
+			case DPIClassification.DPI_120:
+			{
+				paddingRight = PADDING_RIGHT_120DPI;
+				paddingVertical = PADDING_VERTICAL_120DPI;
+				break;
+			}
+            default:
+            {
+                paddingRight = PADDING_RIGHT_DEFAULTDPI;
+                paddingVertical = PADDING_VERTICAL_DEFAULTDPI;
+                break;
+            }
+        }
+    }
+}
+}
\ No newline at end of file