我正在尝试创建一个自定义TextInput组件,该组件的内部有一个标签,标签旁边有实际的输入框。如下图所示(Photoshop切片):

我大部分时间都在工作。但是,当文本到达框的末尾时,它会一直到边框(完全忽略填充),然后当输入更多的字符时,它会将文本的左侧向右推到USERNAME标签(同样,忽略填充)。正如您在这张图片中所看到的(Flex屏幕快照)

除了改变滚动条的皮肤之外,这是我做过的第一个定制组件和皮肤,我已经花了一天的时间来研究它。我知道这可能很容易,但我想不出来。如果有人能告诉我该怎么做的话,我会非常感激的.
我到目前为止的密码是这样的.
com.controls.LabeledTextInput.as:
package com.controls
{
import flash.events.FocusEvent;
import spark.components.TextInput;
import spark.core.IDisplayText;
import mx.core.FlexGlobals;
import mx.styles.CSSStyleDeclaration;
//--------------------------------------
// Styles
//--------------------------------------
/**
* The alpha of the border for this component.
*/
[Style(name="focusBorderAlpha", type="Number", inherit="no", theme="spark", minValue="0.0", maxValue="1.0")]
/**
* The color of the border for this component.
*/
[Style(name="focusBorderColor", type="uint", format="Color", inherit="no", theme="spark")]
/**
* Controls the visibility of the border for this component.
*/
[Style(name="focusBorderVisible", type="Boolean", inherit="no", theme="spark, mobile")]
/**
* Shorthand padding around the textDisplay subcomponent.
* This property works like the CSS padding style. Eg.
* padding: 2 4 2 4 (top right bottom left)
* padding: 2 4 2 (top right/left bottom)
* padding: 2 4 (top/bottom right/left)
* padding: 2 (top/right/bottom/left)
*/
[Style(name="padding", type="String", inherit="no", theme="spark")]
/**
* Padding around the labelDisplay subcomponent.
* This property works like the CSS padding style. Eg.
* padding: 2 4 2 4 (top right bottom left)
* padding: 2 4 2 (top right/left bottom)
* padding: 2 4 (top/bottom right/left)
* padding: 2 (top/right/bottom/left)
*/
[Style(name="labelPadding", type="String", inherit="no", theme="spark")]
//--------------------------------------
// Skin states
//--------------------------------------
/**
* Focus State of the TextInput
*/
[SkinState("focused")]
public class LabeledTextInput extends TextInput
{
[SkinPart(required="false")]
/**
* A skin part that defines the label of the input.
*/
public var labelDisplay:IDisplayText;
/**
* Var for storing the label.
*/
private var _label:String;
/**
* Keeps track of our focus state.
*/
private var inFocus:Boolean;
/**
* Used for setting default property values.
*/
private static var classConstructed:Boolean = classConstruct();
// Set default style values
private static function classConstruct() : Boolean
{
if (!FlexGlobals.topLevelApplication.styleManager.getStyleDeclaration("com.controls.LabeledTextInput"))
{
var labeledTextInputStyles:CSSStyleDeclaration = new CSSStyleDeclaration();
labeledTextInputStyles.defaultFactory = function() : void
{
this.focusBorderAlpha = 1;
this.focusBorderColor = 0xE2E2D9;
this.focusBorderVisible = true;
this.paddingTop = NaN;
this.paddingRight = NaN;
this.paddingBottom = NaN;
this.paddingLeft = NaN;
this.padding = null;
this.labelPadding = null;
}
FlexGlobals.topLevelApplication.styleManager.setStyleDeclaration("com.controls.LabeledTextInput", labeledTextInputStyles, true);
}
return true;
}
public function LabeledTextInput()
{
super();
}
[Bindable]
public function get label() : String
{
return _label;
}
public function set label(value:String) : void
{
if(_label != value)
{
_label = value;
if(labelDisplay != null)
{
labelDisplay.text = value;
}
}
}
/* Implement the getCurrentSkinState() method to set the view state of the skin class. */
override protected function getCurrentSkinState() : String
{
return (inFocus == true) ? "focused" : super.getCurrentSkinState();
}
/* Set the label and attach focus even handlers. */
override protected function partAdded(partName:String, instance:Object) : void
{
super.partAdded(partName, instance);
if (instance == labelDisplay)
{
labelDisplay.text = label;
}
else if(instance == textDisplay)
{
textDisplay.addEventListener(FocusEvent.FOCUS_IN, onFocusInHandler);
textDisplay.addEventListener(FocusEvent.FOCUS_OUT, onFocusOutHandler);
}
}
/* Remove the focus event handlers. */
override protected function partRemoved(partName:String, instance:Object) : void
{
super.partRemoved(partName, instance);
if(instance == textDisplay)
{
textDisplay.removeEventListener(FocusEvent.FOCUS_IN, onFocusInHandler);
textDisplay.removeEventListener(FocusEvent.FOCUS_OUT, onFocusOutHandler);
}
}
/* Handler for FocusIn Event */
private function onFocusInHandler(event:FocusEvent) : void
{
inFocus = true;
invalidateSkinState();
}
/* Handler for FocusOut */
private function onFocusOutHandler(event:FocusEvent) : void
{
inFocus = false;
invalidateSkinState();
}
}
}com.controls.skins.LabeledTextInputSkin.mxml:
<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
alpha.disabledStates="0.5" blendMode="normal">
<fx:Metadata>
<![CDATA[
[HostComponent("com.controls.LabeledTextInput")]
]]>
</fx:Metadata>
<fx:Script fb:purpose="styling">
<![CDATA[
import mx.core.FlexVersion;
private var paddingChanged:Boolean;
/* Define the skin elements that should not be colorized. */
static private const exclusions:Array = ["background", "textDisplay", "promptDisplay", "border"];
/* exclusions before Flex 4.5 for backwards-compatibility purposes */
static private const exclusions_4_0:Array = ["background", "textDisplay", "promptDisplay"];
/**
* @private
*/
override public function get colorizeExclusions() : Array
{
// Since border is styleable via borderColor, no need to allow chromeColor to affect
// the border. This is wrapped in a compatibility flag since this change was added
// in Flex 4.5
if (FlexVersion.compatibilityVersion < FlexVersion.VERSION_4_5)
{
return exclusions_4_0;
}
return exclusions;
}
/* Define the content fill items that should be colored by the "contentBackgroundColor" style. */
static private const contentFill:Array = ["bgFill"];
/**
* @private
*/
override public function get contentItems():Array {return contentFill};
/**
* @private
*/
override protected function commitProperties() : void
{
super.commitProperties();
if (paddingChanged)
{
updatePadding();
paddingChanged = false;
}
}
/**
* @private
*/
override protected function initializationComplete() : void
{
useChromeColor = false;
super.initializationComplete();
}
/**
* Update the display list.
*
* @private
*/
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void
{
var visibleState:Boolean = (getStyle("borderVisible") == true) ? true : false;
border.visible = visibleState;
shadow.visible = visibleState;
if(currentState == 'focused')
{
focusBorder.visible = getStyle("focusBorderVisible");
focusBorderStroke.color = getStyle("focusBorderColor");
focusBorderStroke.alpha = getStyle("focusBorderAlpha");
}
else
{
borderStroke.color = getStyle("borderColor");
borderStroke.alpha = getStyle("borderAlpha");
}
super.updateDisplayList(unscaledWidth, unscaledHeight);
}
/**
* Adjusts the border to be visible and within' the bounds.
*
* @private
*/
private function updateBorderPos() : void
{
if(getStyle("borderVisible") == true || getStyle("focusBorderVisible") )
{
background.left = background.top = background.right = background.bottom = 1;
textDisplay.left = textDisplay.top = textDisplay.right = textDisplay.bottom = 1;
if(labelDisplay)
{
labelDisplay.setLayoutBoundsSize(unscaledWidth - 2, unscaledHeight - 2);
labelDisplay.setLayoutBoundsPosition(1, 1);
}
}
else
{
background.left = background.top = background.right = background.bottom = 0;
textDisplay.left = textDisplay.top = textDisplay.right = textDisplay.bottom = 0;
if(labelDisplay)
{
labelDisplay.setLayoutBoundsSize(unscaledWidth, unscaledHeight);
labelDisplay.setLayoutBoundsPosition(0, 0);
}
}
}
/**
* Adds the padding properties to the controls.
*
* @private
*/
private function updatePadding() : void
{
var sides:Array = [ "Top", "Right", "Bottom", "Left" ];
var padding:Number;
var paddingStr:String;
var paddingArr:Array;
var paddingLen:Number
var side:Number;
var i:String;
/* Set the padding on the textDisplay control.
This will also support for the individual paddingTop,
paddingRight, [...] properties and they will override
the short-hand padding property. */
if(textDisplay)
{
paddingStr = getStyle("padding");
if(paddingStr != null)
{
paddingArr = paddingStr.replace(/^\s+|\s+$/g, '').split(" ");
paddingLen = paddingArr.length;
for(i in sides)
{
side = (paddingLen == 3 && side == 2) ? 1 : Number(i) % paddingLen;
if(textDisplay.getStyle("padding" + sides[i]) != paddingArr[side])
{
textDisplay.setStyle("padding" + sides[i], parseInt(paddingArr[side]));
}
}
}
for (i in sides)
{
padding = getStyle("padding" + sides[i]);
if(!isNaN(padding) && textDisplay.getStyle("padding" + sides[i]) != padding)
textDisplay.setStyle("padding" + sides[i], padding);
}
}
/* Set the padding on the labelDisplay control. */
if(labelDisplay)
{
paddingStr = getStyle("labelPadding");
if(paddingStr != null)
{
paddingArr = paddingStr.replace(/^\s+|\s+$/g, '').split(" ");
paddingLen = paddingArr.length;
for (i in sides)
{
side = (paddingLen == 3 && side == 2) ? 1 : Number(i) % paddingLen;
if(labelDisplay.getStyle("padding" + sides[i]) != paddingArr[side])
labelDisplay.setStyle("padding" + sides[i], paddingArr[side]);
}
}
}
}
/**
* @private
*/
override public function styleChanged(styleProp:String):void
{
var allStyles:Boolean = !styleProp || styleProp == "styleName";
super.styleChanged(styleProp);
if (allStyles || styleProp.indexOf("padding") == 0)
{
paddingChanged = true;
invalidateProperties();
}
}
]]>
</fx:Script>
<fx:Script>
<![CDATA[
/**
* @private
*/
private static const focusExclusions:Array = ["textDisplay"];
/**
* @private
*/
override public function get focusSkinExclusions():Array { return focusExclusions;};
]]>
</fx:Script>
<s:states>
<s:State name="normal"/>
<s:State name="focused"/>
<s:State name="disabled" stateGroups="disabledStates"/>
<s:State name="normalWithPrompt"/>
<s:State name="disabledWithPrompt" stateGroups="disabledStates"/>
</s:states>
<!-- border -->
<!--- @private -->
<s:Rect left="0" right="0" top="0" bottom="0" id="border" radiusX="3" excludeFrom="focused">
<s:stroke>
<!--- @private -->
<s:SolidColorStroke id="borderStroke" weight="1" />
</s:stroke>
</s:Rect>
<!-- focusBorder -->
<!--- @private -->
<s:Rect left="0" right="0" top="0" bottom="0" id="focusBorder" radiusX="3" includeIn="focused">
<s:stroke>
<!--- @private -->
<s:SolidColorStroke id="focusBorderStroke" weight="1" />
</s:stroke>
</s:Rect>
<!-- fill -->
<!--- Defines the appearance of the TextInput component's background. -->
<s:Rect id="background" left="1" right="1" top="1" bottom="1" radiusX="3">
<s:fill>
<!--- @private Defines the background fill color. -->
<s:SolidColor id="bgFill" color="0xFFFFFF" />
</s:fill>
</s:Rect>
<!-- shadow -->
<!--- @private -->
<s:Rect left="1" top="1" right="1" height="1" id="shadow" radiusX="3">
<s:fill>
<s:SolidColor color="0x000000" alpha="0.12" />
</s:fill>
</s:Rect>
<s:HGroup gap="0">
<!--- Defines the Label that is used for prompt text. The includeInLayout property is false so the prompt text does not affect measurement. -->
<s:Label id="labelDisplay"/>
<!-- text -->
<!--- @copy spark.components.supportClasses.SkinnableTextBase#textDisplay -->
<s:RichEditableText id="textDisplay"
verticalAlign="middle"
widthInChars="20"/>
</s:HGroup>
</s:SparkSkin>发布于 2014-03-22 12:56:10
在skinClass...increse “gap”标签和editableText...then检查之间的值.
https://stackoverflow.com/questions/22574032
复制相似问题