Difficulty creating animated skin in Flex 4 - apache-flex

I have been tasked with creating the equivalent Flex 4 implementation of graphical style of the buttons found on this page:
http://h.dwighthouse.com/temp/UDOP/2011-3-25_themeDevGlowing/
Namely, the animated glowing effect on the buttons. I've gotten what I think is the appropriate programmatic gradient-based skin basis, but I have two problems.
One, I can't get any mouse events to respond in the skin. I can't seem to find others with this problem. In the below code, startAnimation is never getting called when a mouse over occurs, but the event is apparently getting registered. To test this code, simply add skinClass="ButtonSkin" to a button declaration in your main application, the code below being the ButtonSkin.mxml file.
<?xml version="1.0" encoding="utf-8"?>
<s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
initialize="init()"
mouseEnabled="true">
<fx:Metadata>
[HostComponent("spark.components.Button")]
</fx:Metadata>
<fx:Script>
<![CDATA[
import flash.events.Event;
[Bindable]
private var animatedAlpha:Number = 0.8;
private var animationDirection:Number = -1;
private function backAndForth(value:Number, max:Number, min:Number, increment:Number):Number {
value += (animationDirection * increment);
if (value < min || value > max)
{
animationDirection *= -1;
value += (animationDirection * increment * 2);
}
return value;
}
private function startAnimation(e:MouseEvent):void {
animatedAlpha = backAndForth(animatedAlpha, 0.8, 0.3, 0.1); // Or something
systemManager.addEventListener(MouseEvent.MOUSE_OUT, endAnimation);
}
private function endAnimation(e:MouseEvent):void {
animatedAlpha = backAndForth(animatedAlpha, 0.8, 0.3, 0.1); // Or something
systemManager.removeEventListener(MouseEvent.MOUSE_OUT, endAnimation);
}
private function init():void {
parent.mouseChildren = true; // Otherwise mouse events don't fire in the skin
clickableArea.addEventListener(MouseEvent.MOUSE_OVER, startAnimation);
}
]]>
</fx:Script>
<s:states>
<s:State name="up" />
<s:State name="over" />
<s:State name="down" />
<s:State name="disabled" />
</s:states>
<s:Group top="0" bottom="0" left="0" right="0" id="clickableArea">
<s:Rect top="0" bottom="0" left="0" right="0" radiusX="8" radiusY="8">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="#000000" color.down="#bb0000" color.disabled="#3b3b3b" ratio="0" />
<s:GradientEntry color="#353535" color.down="#ff0000" color.disabled="#555555" ratio="1" />
</s:LinearGradient>
</s:fill>
</s:Rect>
<s:Rect top="0" bottom="0" left="0" right="0" radiusX="8" radiusY="8">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color.over="#8f1b1b" alpha="0" ratio="0" />
<s:GradientEntry color.over="#8f1b1b" alpha="0" ratio="0.4" />
<s:GradientEntry color.over="#8f1b1b" alpha="{animatedAlpha}" alpha.down="0" ratio="1" />
</s:LinearGradient>
</s:fill>
</s:Rect>
<s:Rect top="0" bottom="0" left="0" right="0" radiusX="8" radiusY="8">
<s:stroke>
<s:SolidColorStroke color="#000000" color.disabled="#333333" weight="1" />
</s:stroke>
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="#ffffff" color.disabled="#9e9e9e" alpha="0.6" alpha.down="0.7" ratio="0" />
<s:GradientEntry color="#ffffff" color.disabled="#848484" alpha="0.2" alpha.down="0.4" ratio="0.45" />
<s:GradientEntry color="#ffffff" alpha="0" ratio="0.46" />
</s:LinearGradient>
</s:fill>
</s:Rect>
<s:Label id="labelDisplay" color="#ffffff" color.disabled="#aaaaaa" textAlign="center" baseline="center" paddingTop="7" paddingBottom="5" paddingLeft="10" paddingRight="10">
<s:filters>
<s:DropShadowFilter distance="0" angle="45" blurX="5" blurY="5" />
</s:filters>
</s:Label>
</s:Group>
EDIT I found out why mouse events weren't firing. The button apparently has mouseChildren false by default, which specifically prevents events from firing lower than itself. Using parent.mouseChildren = true; in the constructor fixes this issue. On to the next part of the question: continuous animation.
Other than that, I'd appreciate some help or point me in the right direction of calling a function every frame, and the ability to turn said incremental call on and off using mouse events. (If that's not how you animate in Flex, forgive me, I know nothing about Flash-based animation.) Thanks!

Answers to both questions have been found:
Buttons prevent their children (including Skins) from receiving mouse events. By setting parent.mouseChildren = true; in the skin's initializing function, mouse events are received normally.
Turns out you can animate in Flex (Actionscript) the same way you animate in Javascript: setInterval and clearInterval.

Related

Custom drop down on mouse over

I'm making a custom component that shows a little drop down area after you hover on the username. I'm using two states, up and hover to toggle my drop down box.
My problem is that it thinks I'm leaving the component level Group after I leave the username. Then the second level group (my drop down) disappears.
I've tried re-attaching an event handler to my component level Group on a callLater in my mouse over function but that didn't work.
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
mouseOver="groupLogIn_mouseOverHandler(event)"
mouseOut="groupLogIn_mouseOutHandler(event)"
>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import spark.skins.SparkSkin;
protected function groupLogIn_mouseOverHandler(event:MouseEvent):void
{
this.currentState = "hover";
}
protected function groupLogIn_mouseOutHandler(event:MouseEvent):void
{
this.currentState = "up"
}
]]>
</fx:Script>
<s:states>
<s:State name="up"/>
<s:State name="hover"/>
</s:states>
<s:Label id="lblUsername" color="0xffffff" fontSize="14" right="18" top="5"/>
<s:Group includeIn="hover" width="160" height="110" top="20" right="0" >
<s:Rect top="0" right="0" bottom="0" left="0">
<s:fill>
<s:SolidColor color="0x1a1a1a"/>
</s:fill>
</s:Rect>
</s:Group>
</s:Group>
You need a "hitzone" for your mouse events. Right now parts of your component are completely transparent. When the mouse goes over a transparent zone, the MOUSE_OUT event is triggered. (When I say 'transparent', µi actually mean there's nothing there at all).
Luckily this can easily be fixed: just add a Rect that covers the entire area below the other components and set its alpha to 0. This makes the Rect invisible to the user, but it can still react to mouse events.
<s:Rect id="hitzone" top="0" right="0" bottom="0" left="0">
<s:fill>
<s:SolidColor alpha="0" />
</s:fill>
</s:Rect>
<s:Label id="lblUsername" />
...

Flex mouse over area issue (custom button skin)

I created a custom button skin:
<?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:mx="library://ns.adobe.com/flex/mx"
minWidth="65" minHeight="22"
creationComplete="GlassButtonSkin_creationCompleteHandler(event)">
<fx:Metadata>[HostComponent("spark.components.Button")]</fx:Metadata>
<fx:Declarations>
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.graphics.RadialGradient;
import spark.effects.Fade;
import spark.effects.animation.RepeatBehavior;
[Bindable]
private var rectRollOverEffect:Rect = new Rect();
private var radialGradientRollOverEffect:RadialGradient = new RadialGradient();
private var gradientEntryRollOverEffect1:GradientEntry = new GradientEntry(0x8dbdff,NaN,0.7);
private var gradientEntryRollOverEffect2:GradientEntry = new GradientEntry(0x8dbdff,NaN,0);
private var indexOfRollOverEffect:int;
private var myFade:Fade;
protected function GlassButtonSkin_creationCompleteHandler(event:FlexEvent):void{
parent.mouseChildren = true;
this.addEventListener(MouseEvent.MOUSE_MOVE,mouseMoveHandler,true);
this.addEventListener(MouseEvent.MOUSE_OUT,mouseOutHandler,true);
this.addEventListener(MouseEvent.MOUSE_OVER,mouseOverHandler,true);
this.addElement(rectRollOverEffect);
indexOfRollOverEffect = this.getElementIndex(rectRollOverEffect);
this.removeElementAt(indexOfRollOverEffect);
}
private function mouseOverHandler(event:MouseEvent):void{
if(this.currentState == "disabled")
return;
createRollOverEffect(event,0);
myFade = new Fade(this.getElementAt(indexOfRollOverEffect));
myFade.alphaFrom = 0;
myFade.alphaTo = 1;
myFade.duration = 200;
myFade.end();
myFade.play();
}
private function mouseMoveHandler(event:MouseEvent):void{
if(this.currentState == "disabled")
return;
this.removeElementAt(indexOfRollOverEffect);
createRollOverEffect(event,1);
}
private function mouseOutHandler(event:MouseEvent):void{
if(this.currentState == "disabled")
return;
this.removeElementAt(indexOfRollOverEffect);
}
private function createRollOverEffect(event:MouseEvent,alpha:int):void{
rectRollOverEffect.alpha = alpha;
rectRollOverEffect.left = 2;
rectRollOverEffect.right = 2;
rectRollOverEffect.bottom = 2;
rectRollOverEffect.top = 2;
rectRollOverEffect.radiusX = 4;
rectRollOverEffect.radiusY = 4;
radialGradientRollOverEffect.entries = [gradientEntryRollOverEffect1,gradientEntryRollOverEffect2];
radialGradientRollOverEffect.x = event.localX;
radialGradientRollOverEffect.y = height-2;
radialGradientRollOverEffect.scaleX = width/1.5;
radialGradientRollOverEffect.scaleY = height;
rectRollOverEffect.fill = radialGradientRollOverEffect;
this.addElementAt(rectRollOverEffect,indexOfRollOverEffect);
}
]]>
</fx:Script>
<s:states>
<s:State name="up"/>
<s:State name="over"/>
<s:State name="down"/>
<s:State name="disabled"/>
</s:states>
<s:transitions>
<s:Transition fromState="over" toState="disabled">
<s:CallAction target="{this}" functionName="removeElement" args="{[this.rectRollOverEffect]}"/>
</s:Transition>
</s:transitions>
<!-- outer border -->
<s:Rect left="0" right="0" top="0" bottom="0" id="outerBorder" radiusX="4" radiusY="4">
<s:stroke>
<s:SolidColorStroke id="outerBorderStroke" weight="1" color="#ffffff" />
</s:stroke>
</s:Rect>
<!-- inner border -->
<s:Rect left="1" right="1" top="1" bottom="1" id="innerBorder" radiusX="4" radiusY="4">
<s:stroke>
<s:SolidColorStroke id="innerBorderStroke" weight="1" color="#000000"/>
</s:stroke>
</s:Rect>
<!-- fill -->
<!--- Defines the appearance of the Button component's background. -->
<s:Rect id="background" left="1" right="1" top="1" bottom="1">
<s:fill>
<s:SolidColor alpha="0.5" color="#000000"/>
</s:fill>
</s:Rect>
<s:Rect id="backgroundTopPart" left="1" right="1" top="1" height="50%"
includeIn="up,over,disabled">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="#ffffff" alpha="0.5" ratio="0.1"/>
<s:GradientEntry color="#ffffff" alpha="0.1"/>
</s:LinearGradient>
</s:fill>
</s:Rect>
<s:Label id="labelDisplay"
text="Send"
textAlign="center"
verticalAlign="middle"
color="#FFFFFF"
horizontalCenter="0" verticalCenter="1"
left="10" right="10" top="2" bottom="2">
</s:Label>
<s:Rect id="disableForeground" left="0" right="0" top="0" bottom="0"
includeIn="disabled">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="#7B7B7B" alpha="0.6" ratio="0.1"/>
<s:GradientEntry color="#aaaaaa" alpha="0.3"/>
</s:LinearGradient>
</s:fill>
</s:Rect>
</s:SparkSkin>
The problem is that my hitarea seems to be wrong. When I click, it is OK, the area is right but with the mouse over event, the area seems to be different and smaller than the click area. I just don't understand why.
I even tried to change manually the hit area of the button skin by adding a line this.hitArea = this.interactiveGroup Where interactiveGroup is a group that contains the component borders but it didn't change anything.
I think its to do with you labelDisplay element of the skin. It has a right and left of 10.... if the right and left are set to 0, then the effect appears straight off, withough being too small.

Flex 4 button skin disabled alpha setting ignored?

I attempted to build a Flex 4 skin for a Spark button, typical practice. I adjusted the colors and other styles to my liking, including using dot selectors to specify alternate colors and such during different states. However, these are all ignored when the button is disabled. Regardless of what I do, in the disabled state, my button always has the wrong color and is alpha'd to 0.5 (even if I specifically state that alpha.disabled="1"). All the other skin states work as expected. What is going on here?
This is my custom skin. If it were working correctly, it would appear to have no shadow or highlight, and would be a gradient grey color. Instead, it appears as a 50% alpha version of the up state (shiny green).
<?xml version="1.0" encoding="utf-8"?>
<s:SparkButtonSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
minWidth="21" minHeight="21" alpha.disabled="1">
<fx:Metadata>
<![CDATA[
[HostComponent("spark.components.Button")]
]]>
</fx:Metadata>
<s:states>
<s:State name="up" />
<s:State name="over" />
<s:State name="down" />
<s:State name="disabled" />
</s:states>
<s:Rect id="backgroundAndShadow" left="0" right="0" top="0" bottom="0" radiusX="5" radiusY="5">
<s:filters>
<s:DropShadowFilter blurX="5" blurY="5" blurX.down="3" blurY.down="3" alpha="0.5" distance="1" distance.down="0" angle="90" excludeFrom="disabled" />
</s:filters>
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color.up="#00AD00" color="#007A00" color.disabled="#cccccc" />
<s:GradientEntry color.up="#29FF29" color="#00F500" color.disabled="#bbbbbb" />
</s:LinearGradient>
</s:fill>
</s:Rect>
<s:Rect id="highlight" left="1" right="1" top="1" height="50%" topLeftRadiusX="4" topLeftRadiusY="4" topRightRadiusX="4" topRightRadiusY="4" excludeFrom="disabled">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="#ffffff" alpha="0.8" />
<s:GradientEntry color="#ffffff" alpha="0.3" />
</s:LinearGradient>
</s:fill>
</s:Rect>
<s:Label id="labelDisplay"
textAlign="center"
horizontalCenter="0" verticalCenter="1" verticalAlign="middle"
color="#ffffff" color.disabled="#555555"
fontWeight="bold"
left="2" right="2" top="2" bottom="2">
<s:filters>
<s:DropShadowFilter blurX="3" blurY="3" alpha="0.5" distance="1" distance.down="0" angle="90" excludeFrom="disabled" />
</s:filters>
</s:Label>
</s:SparkButtonSkin>
I also did this with an automatically generated skin for the Button using Flash Builder's skin creation wizard/dialog. Even then, specifically setting the alpha to 1 in disabled mode had no effect.
Edit
This is the code used to create and then disable the button:
_action1Button = new Action1Button();
view.actionGroup.addElement(_action1Button);
_action1Button.enabled = false;
The error was that _action1Button is not the actual button, rather, it's the container of the button. Doh! Switching it to _action1Button.actionButton.enabled = false; fixed the issue.
Your skin works fine for me. I get a green button in the enabled state then a grey gradient without drop shadow when enabled is false. I tested it like this (where TestSkin is your skin posted above):
<s:Button skinClass="TestSkin" enabled="false" />
I assume the problem has to do with how you are using the skin. Can you post the code where the button itself is defined?

Is this a PrintDataGrid bug or restriction or my lack of understanding?

I'm trying to implement PrintDataGrid in my application and I'm encountering a peculiar problem. The printout is skipping last several rows in the printout of each page.
I have narrowed down to what's causing this issue. My application-level custom skin provides Flex scrolling capability to the entire application. Presence of this scrollbar in the custom skin is causing PrintDataGrid to skip last rows. In fact, number of rows skipped depends on the height of the browser. If you reduce the browser height, you skip more rows!
Is this a bug PrintDataGrid or a restriction (cannot have PrintDataGrid within Scroller) or I'm missing something?
Please help as I'm struggling with this for several days!
Here is simple code to reproduce the issue:
Main Application:
Application custom skin class:ApplicationSkinCustom.mxml
============================================
#see spark.components.Application
#langversion 3.0
#playerversion Flash 10
#playerversion AIR 1.5
#productversion Flex 4
-->
<fx:Metadata>
<![CDATA[
/**
* A strongly typed property that references the component to which this skin is applied.
*/
[HostComponent("spark.components.Application")]
]]>
</fx:Metadata>
<fx:Script fb:purpose="styling">
<![CDATA[
/**
* #private
*/
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number) : void
{
bgRectFill.color = getStyle('backgroundColor');
super.updateDisplayList(unscaledWidth, unscaledHeight);
}
]]>
</fx:Script>
<s:states>
<s:State name="normal" />
<s:State name="disabled" />
<s:State name="normalWithControlBar" />
<s:State name="disabledWithControlBar" />
</s:states>
<!-- fill -->
<!---
A rectangle with a solid color fill that forms the background of the application.
The color of the fill is set to the Application's backgroundColor property.
-->
<s:Rect id="backgroundRect" left="0" right="0" top="0" bottom="0" >
<s:fill>
<s:SolidColor id="bgRectFill" color="#FFFFFF"/>
</s:fill>
</s:Rect>
<s:Scroller left="1" top="1" right="1" bottom="1" id="scroller">
<s:Group left="0" right="0" top="0" bottom="0">
<s:layout>
<s:VerticalLayout gap="0" horizontalAlign="justify" />
</s:layout>
<!---
#private
Application Control Bar
-->
<s:Group
id="topGroup"
minWidth="0"
minHeight="0"
includeIn="normalWithControlBar, disabledWithControlBar"
>
<!-- layer 0: control bar highlight -->
<s:Rect left="0" right="0" top="0" bottom="1" >
<s:stroke>
<s:LinearGradientStroke rotation="90" weight="1">
<s:GradientEntry color="0xFFFFFF" />
<s:GradientEntry color="0xD8D8D8" />
</s:LinearGradientStroke>
</s:stroke>
</s:Rect>
<!-- layer 1: control bar fill -->
<s:Rect left="1" right="1" top="1" bottom="2" >
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xEDEDED" />
<s:GradientEntry color="0xCDCDCD" />
</s:LinearGradient>
</s:fill>
</s:Rect>
<!-- layer 2: control bar divider line -->
<s:Rect left="0" right="0" bottom="0" height="1" alpha="0.55">
<s:fill>
<s:SolidColor color="0x000000" />
</s:fill>
</s:Rect>
<!-- layer 3: control bar -->
<!--- #copy spark.components.Application#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>
<!--- #copy spark.components.SkinnableContainer#contentGroup -->
<!--<s:Group id="contentGroup" width="100%" height="100%" minWidth="0" minHeight="0" />-->
<s:Group id="contentGroup" left="0" right="0" top="0" bottom="0" />
</s:Group>
</s:Scroller>
This is apparently a known bug with the Flex printing library and Scroller controls. You can read about my discussions on this here:
http://forums.adobe.com/message/3626759
The first thing I would try is getting rid of the custom skin, processing your print job, and then re-applying the custom skin. This might do the trick. If that does work, but doesn't look the way you want, then you can work on creating a variant of your custom application skin that doesn't have a scroller. You would apply that before starting the print job, and then restore the original custom application skin after the print job completes.
The user may briefly see the "alternate" version of your app when they click the print button, but it should only be for a split second at most.
-Josh

Flex 4: How to skin a spark volumebar to make it work like a HSlider?

Can anyone point me in the direction of skinning a video player volumebar? I want a mute button on the left side and then an HSlider to the right that is always open (no popups).
I've managed to change the skin to use a custom track button and a custom thumb button and it mostly looks how I want.
I can't seem to figure out how to make the thumb slide horizontally across the track and how to hook it into the videoplayer. The thumb just wiggles a little up and down.
I realize I can make a separate HSlider and button and then attach them to the videoplayer controls, I was just hoping since the functionality is already built in that I could override a few skins and be done with it.
I had the same issue today and found that the solution was to reimplement VolumeBar extends VSlider so that HVolumeBar extends HSlider then alter updateSkinDisplayList() so the thumb position works correctly. I tried the rotation approach without success. I played with the skins a bit also.
override protected function updateSkinDisplayList():void
{
if (!thumb || !track)
return;
var thumbRange:Number = track.getLayoutBoundsWidth() - thumb.getLayoutBoundsWidth();
var range:Number = maximum - minimum;
// calculate new thumb position.
var thumbPosTrackX:Number;
// if muted, it's 0. otherwise, calculate it normally
// TODO (rfrishbe): should probably use setValue(0) and listen for CHANGE on the VideoPlayer
// instead of VALUE_COMMIT.
if (!muted)
thumbPosTrackX = (range > 0) ? (((pendingValue - minimum) / range) * thumbRange) : 0;
else
thumbPosTrackX = thumbRange;
// convert to parent's coordinates.
var thumbPos:Point = track.localToGlobal(new Point(thumbPosTrackX,0));
var thumbPosParentX:Number = thumb.parent.globalToLocal(thumbPos).x;
thumb.setLayoutBoundsPosition(Math.round(thumbPosParentX), thumb.getLayoutBoundsY() );
}
Edit: Horizontal Volume Bar Skin
<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" minWidth="11" alpha.disabled=".5">
<!-- host component -->
<fx:Metadata>
/**
* #copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent("grammit.media.HorizontalVolumeBar")]
</fx:Metadata>
<fx:Script fb:purpose="styling">
/* Define the skin elements that should not be colorized. */
static private const exclusions:Array = ["muteButton", "track", "thumb"];
/**
* #private
*/
override public function get colorizeExclusions():Array {return exclusions;}
/**
* #private
*/
override protected function initializationComplete():void
{
useChromeColor = true;
super.initializationComplete();
}
</fx:Script>
<s:states>
<s:State name="normal" />
<s:State name="open" />
<s:State name="disabled" />
</s:states>
<!--- The PopUpAnchor control that contains the drop-down slider control. -->
<s:PopUpAnchor id="popup" displayPopUp.normal="false" displayPopUp.open="true" includeIn="open"
left="0" right="0" top="0" bottom="0" popUpPosition="left" itemDestructionPolicy="auto">
<!--- #copy spark.components.mediaClasses.VolumeBar#dropDown -->
<s:Group id="dropDown" width="84" height="28" verticalCenter="0">
<!-- dropshadow for the dropdown -->
<s:Rect left="0" top="0" right="0" bottom="0">
<s:filters>
<s:DropShadowFilter knockout="true" blurX="20" blurY="20" alpha="0.32" distance="11" angle="90" />
</s:filters>
<s:fill>
<s:SolidColor color="0x000000" />
</s:fill>
</s:Rect>
<!-- background for the popup -->
<s:Rect left="0" right="0" top="0" bottom="0">
<s:fill>
<s:LinearGradient rotation="90">
<s:GradientEntry color="0xFFFFFF"/>
<s:GradientEntry color="0xDCDCDC"/>
</s:LinearGradient>
</s:fill>
<s:stroke>
<s:SolidColorStroke color="0x000000" />
</s:stroke>
</s:Rect>
<!--- The skin pat that defines the drop-down slider track. -->
<s:Button id="track" verticalCenter="0" left="6" right="7" minWidth="33" width="100"
skinClass="grammit.skins.HorizontalVolumeBarTrackSkin" />
<!--- The skin pat that defines the thumb in the drop-down slider track. -->
<s:Button id="thumb" verticalCenter="0" width="11" height="11"
skinClass="spark.skins.spark.mediaClasses.normal.VolumeBarThumbSkin" />
</s:Group>
</s:PopUpAnchor>
<!--- #copy spark.components.mediaClasses.VolumeBar#muteButton -->
<s:MuteButton id="muteButton" left="0" right="0" top="0" bottom="0" focusEnabled="false"
skinClass="spark.skins.spark.mediaClasses.normal.MuteButtonSkin" />
</s:SparkSkin>
I couldn't find a good solution to this either so I just used rotation=90 to volumebar and rotation=-90 to what ever needed to be rotated back inside the volumebarskin.

Resources