我想通過擴展標準組件和創建自定義皮膚來解決它。
我的組件的版本:
package
{
import flash.events.MouseEvent;
import mx.managers.PopUpManager;
import spark.components.TextArea;
import spark.components.TitleWindow;
[SkinState("disabledSuccessful")]
[SkinState("disabledWithControlBarSuccessful")]
[SkinState("inactiveSuccessful")]
[SkinState("inactiveWithControlBarSuccessful")]
[SkinState("normalSuccessful")]
[SkinState("normalWithControlBarSuccessful")]
public class SuccessfulTitleWindow extends TitleWindow
{
public function SuccessfulTitleWindow()
{
title = "Output: ";
}
[SkinPart(required = "false")]
public var textContainer:TextArea;
private var success:Boolean;
private var textChanged:Boolean;
private var textValue:String;
/**
* @inheritDoc
*/
override protected function commitProperties():void
{
super.commitProperties();
if (textChanged && textContainer)
{
textContainer.text = textValue;
textChanged = false;
}
}
/**
* @inheritDoc
*/
override protected function getCurrentSkinState():String
{
var skinState:String = super.getCurrentSkinState();
return success ? skinState + "Successful" : skinState;
}
/**
* @inheritDoc
*/
override protected function partAdded(partName:String, instance:Object):void
{
super.partAdded(partName, instance);
if (instance == textContainer)
{
textChanged = true;
invalidateProperties();
}
}
public function setText(text:String):void
{
if (text == textValue)
return;
success = text && text.indexOf("SUCCESS") != -1;
invalidateSkinState();
textValue = text;
textChanged = true;
invalidateProperties();
}
/**
* @inheritDoc
*/
override protected function closeButton_clickHandler(event:MouseEvent):void
{
super.closeButton_clickHandler(event);
PopUpManager.removePopUp(this);
}
}
}
皮膚(基於標準皮):
<?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" blendMode="normal" mouseEnabled="false"
minWidth="76" minHeight="76" alpha.disabledGroup="0.5" width="400">
<fx:Metadata>[HostComponent("SuccessfulTitleWindow")]</fx:Metadata>
<fx:Script fb:purpose="styling">
/* Define the skin elements that should not be colorized.
For panel, border and title background are skinned, but the content area and title text are not. */
static private const exclusions:Array = ["background", "titleDisplay", "contentGroup"];
/**
* @private
*/
override public function get colorizeExclusions():Array {return exclusions;}
/**
* @private
*/
override protected function initializationComplete():void
{
useChromeColor = true;
super.initializationComplete();
}
/**
* @private
*/
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
if (getStyle("borderVisible") == true)
{
border.visible = true;
background.left = background.top = background.right = background.bottom = 1;
contents.left = contents.top = contents.right = contents.bottom = 1;
}
else
{
border.visible = false;
background.left = background.top = background.right = background.bottom = 0;
contents.left = contents.top = contents.right = contents.bottom = 0;
}
dropShadow.visible = getStyle("dropShadowVisible");
var cr:Number = getStyle("cornerRadius");
var withControls:Boolean =
(currentState == "disabledWithControlBar" ||
currentState == "normalWithControlBar" ||
currentState == "inactiveWithControlBar");
if (cornerRadius != cr)
{
cornerRadius = cr;
dropShadow.tlRadius = cornerRadius;
dropShadow.trRadius = cornerRadius;
dropShadow.blRadius = withControls ? cornerRadius : 0;
dropShadow.brRadius = withControls ? cornerRadius : 0;
setPartCornerRadii(topMaskRect, withControls);
setPartCornerRadii(border, withControls);
setPartCornerRadii(background, withControls);
}
if (bottomMaskRect) setPartCornerRadii(bottomMaskRect, withControls);
borderStroke.color = getStyle("borderColor");
borderStroke.alpha = getStyle("borderAlpha");
backgroundFill.color = getStyle("backgroundColor");
backgroundFill.alpha = getStyle("backgroundAlpha");
super.updateDisplayList(unscaledWidth, unscaledHeight);
}
/**
* @private
*/
private function setPartCornerRadii(target:Rect, includeBottom:Boolean):void
{
target.topLeftRadiusX = cornerRadius;
target.topRightRadiusX = cornerRadius;
target.bottomLeftRadiusX = includeBottom ? cornerRadius : 0;
target.bottomRightRadiusX = includeBottom ? cornerRadius : 0;
}
private var cornerRadius:Number;
</fx:Script>
<s:states>
<s:State name="normal" stateGroups="normalGroup" />
<s:State name="inactive" stateGroups="inactiveGroup" />
<s:State name="disabled" stateGroups="disabledGroup" />
<s:State name="normalWithControlBar" stateGroups="withControls, normalGroup" />
<s:State name="inactiveWithControlBar" stateGroups="withControls, inactiveGroup" />
<s:State name="disabledWithControlBar" stateGroups="withControls, disabledGroup" />
<s:State name="normalSuccessful" stateGroups="successfulGroup, normalGroup" />
<s:State name="inactiveSuccessful" stateGroups="inactiveGroup,successfulGroup" />
<s:State name="disabledSuccessful" stateGroups="successfulGroup,disabledGroup" />
<s:State name="normalWithControlBarSuccessful" stateGroups="withControls,successfulGroup,normalGroup" />
<s:State name="inactiveWithControlBarSuccessful" stateGroups="withControls, inactiveGroup, successfulGroup" />
<s:State name="disabledWithControlBarSuccessful" stateGroups="withControls, successfulGroup, disabledGroup" />
</s:states>
<!--- drop shadow can't be hittable so it stays sibling of other graphics @private-->
<s:RectangularDropShadow id="dropShadow" blurX="20" blurY="20" alpha="0.32"
alpha.inactiveGroup="0.22" distance="11" distance.inactiveGroup="7"
angle="90" color="0x000000" left="0" top="0" right="0" bottom="0"/>
<!--- drop shadow can't be hittable so all other graphics go in this group -->
<s:Group left="0" right="0" top="0" bottom="0">
<!--- top group mask @private-->
<s:Group left="1" top="1" right="1" bottom="1" id="topGroupMask">
<!--- @private-->
<s:Rect id="topMaskRect" left="0" top="0" right="0" bottom="0">
<s:fill>
<s:SolidColor alpha="0"/>
</s:fill>
</s:Rect>
</s:Group>
<!--- bottom group mask @private-->
<s:Group left="1" top="1" right="1" bottom="1" id="bottomGroupMask"
includeIn="withControls">
<!--- @private-->
<s:Rect id="bottomMaskRect" left="0" top="0" right="0" bottom="0">
<s:fill>
<s:SolidColor alpha="0"/>
</s:fill>
</s:Rect>
</s:Group>
<!--- layer 1: border @private -->
<s:Rect id="border" left="0" right="0" top="0" bottom="0" >
<s:stroke>
<!--- Defines the TitleWindowSkin class's border stroke. The default value is 1. -->
<s:SolidColorStroke id="borderStroke" weight="1" />
</s:stroke>
</s:Rect>
<!-- layer 2: background fill -->
<!--- Defines the appearance of the TitleWindowSkin class's background. -->
<s:Rect id="background" left="1" top="1" right="1" bottom="1">
<s:fill>
<!--- Defines the TitleWindowSkin class's background fill. The default color is 0xFFFFFF. -->
<s:SolidColor id="backgroundFill" color="#FFFFFF"/>
</s:fill>
</s:Rect>
<!-- layer 3: contents -->
<!--- Contains the vertical stack of title bar content and control bar. -->
<s:Group left="1" right="1" top="1" bottom="1" id="contents">
<s:layout>
<s:VerticalLayout gap="0" horizontalAlign="justify" />
</s:layout>
<!--- @private -->
<s:Group id="topGroup" mask="{topGroupMask}">
<!--- layer 0: title bar fill @private -->
<s:Rect id="tbFill" left="0" right="0" top="0" bottom="1">
<s:fill>
<s:SolidColor color="0xFF0000" color.successfulGroup="0x00ff6b" alpha.inactiveGroup="0.8" />
</s:fill>
</s:Rect>
<!--- layer 1: title bar highlight @private -->
<s:Rect id="tbHilite" left="0" right="0" top="0" bottom="0">
<s:stroke>
<s:LinearGradientStroke rotation="90" weight="1">
<s:GradientEntry color="0xE6E6E6" />
<s:GradientEntry color="0xFFFFFF" alpha="0.22"/>
</s:LinearGradientStroke>
</s:stroke>
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xFFFFFF" alpha="0.15" />
<s:GradientEntry color="0xFFFFFF" alpha="0.15" ratio="0.44"/>
<s:GradientEntry color="0xFFFFFF" alpha="0" ratio="0.4401"/>
</s:LinearGradient>
</s:fill>
</s:Rect>
<!--- layer 2: title bar divider @private -->
<s:Rect id="tbDiv" left="0" right="0" height="1" bottom="0">
<s:fill>
<s:SolidColor color="0x000000" alpha="0.75" />
</s:fill>
</s:Rect>
<!-- layer 3: text -->
<!--- @copy spark.components.Panel#titleDisplay -->
<s:Label id="titleDisplay" maxDisplayedLines="1"
left="9" right="36" top="1" bottom="0" minHeight="30"
verticalAlign="middle" fontWeight="bold" />
<!-- layer 4: moveArea -->
<!--- @copy spark.components.TitleWindow#moveArea -->
<s:Group id="moveArea" left="0" right="0" top="0" bottom="0" />
<!--- @copy spark.components.TitleWindow#closeButton -->
<s:Button id="closeButton" skinClass="spark.skins.spark.TitleWindowCloseButtonSkin"
width="15" height="15" right="7" top="7" />
</s:Group>
<!--
Note: setting the minimum size to 0 here so that changes to the host component's
size will not be thwarted by this skin part's minimum size. This is a compromise,
more about it here: http://bugs.adobe.com/jira/browse/SDK-21143
-->
<!--- @copy spark.components.SkinnableContainer#contentGroup -->
<s:Group id="contentGroup" width="100%" height="100%" minWidth="0" minHeight="0">
<s:TextArea id="textContainer" width="100%" height="100%"
paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10"
borderVisible="false" editable="false" fontFamily="Courier New"/>
</s:Group>
<!--- @private -->
<s:Group id="bottomGroup" minWidth="0" minHeight="0"
includeIn="withControls">
<s:Group left="0" right="0" top="0" bottom="0" mask="{bottomGroupMask}">
<!-- layer 0: control bar divider line -->
<s:Rect left="0" right="0" top="0" height="1" alpha="0.22">
<s:fill>
<s:SolidColor color="0x000000" />
</s:fill>
</s:Rect>
<!-- layer 1: control bar highlight -->
<s:Rect left="0" right="0" top="1" bottom="0">
<s:stroke>
<s:LinearGradientStroke rotation="90" weight="1">
<s:GradientEntry color="0xFFFFFF" />
<s:GradientEntry color="0xD8D8D8" />
</s:LinearGradientStroke>
</s:stroke>
</s:Rect>
<!-- layer 2: control bar fill -->
<s:Rect left="1" right="1" top="2" bottom="1">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xEDEDED"/>
<s:GradientEntry color="0xCDCDCD"/>
</s:LinearGradient>
</s:fill>
</s:Rect>
</s:Group>
<!--- @copy spark.components.Panel#controlBarGroup -->
<s:Group id="controlBarGroup" left="0" right="0" top="1" bottom="1" minWidth="0" minHeight="0">
<s:layout>
<s:HorizontalLayout paddingLeft="10" paddingRight="10" paddingTop="7" paddingBottom="7" gap="10" />
</s:layout>
</s:Group>
</s:Group>
</s:Group>
</s:Group>
</s:SparkSkin>
而簡單的應用程序進行測試:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:local="*">
<s:VGroup verticalCenter="0" horizontalCenter="0">
<local:SuccessfulTitleWindow skinClass="SuccessfulTitleWindowSkin" id="window" />
<s:TextInput change="window.setText(event.currentTarget.text)" />
</s:VGroup>
</s:Application>
是不是真的什麼更快/更簡單..? :( – alfongj
嗯......這是複雜的嗎?事情是,在Flex4特別是火花控制器和視圖是真的很好地分開......有所有優點和缺點 所有你需要做的是複製原件,然後調整第184至194行符合你的需求,我知道Spark皮膚起初看起來很困難和複雜,但你肯定會在一段時間後開始喜歡它;-) –