Amy
Amy

Reputation: 109

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.

Upvotes: 1

Views: 1784

Answers (2)

Laramie
Laramie

Reputation: 5587

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>

Upvotes: 4

Mikko Torniainen
Mikko Torniainen

Reputation: 11

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.

Upvotes: 1

Related Questions