Creating a custom Halo Accordion header skin in Flex 4

by Peter deHaan on June 21, 2009

in Accordion, beta1

The following example shows how you can style the Halo Accordion header (with default Spark skin) in Flex 4 by creating a new skin based on the default Spark skin and modifying the various skin parts.

The default Halo Accordion header Spark skin can be found at \frameworks\projects\sparkskins\src\mx\skins\spark\AccordionHeaderSkin.mxml.

Full code after the jump.

The following example(s) require Flash Player 10 and the Adobe Flex 4 SDK. To download the Adobe Flash Builder 4 beta, check out the Adobe Flash Builder 4 page on the Adobe Labs site. To download the latest build of the Flex 4 SDK, see http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+4. For instructions on using the beta Flex 4 SDK in Flex Builder 3, see "Using the beta Flex 4 SDK in Flex Builder 3".

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2009/06/21/creating-a-custom-halo-accordion-header-skin-in-flex-4/ -->
<s:Application name="Accordion_SparkSkin_headerStyleName_skin_test"
        xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:mx="library://ns.adobe.com/flex/halo"
        xmlns:s="library://ns.adobe.com/flex/spark">

    <fx:Style>
        .customAccordionHeadStyles {
            skin: ClassReference("skins.CustomAccordionHeaderSkin");
        }
    </fx:Style>

    <mx:Accordion id="accordion"
            headerStyleName="customAccordionHeadStyles"
            left="20" right="20" top="20" bottom="20">
        <mx:VBox label="Red" width="100%" height="100%">
            <mx:Text text="Panel 1" />
        </mx:VBox>
        <mx:VBox label="Orange" width="100%" height="100%">
            <mx:Text text="Panel 2" />
        </mx:VBox>
        <mx:VBox label="Yellow" width="100%" height="100%">
            <mx:Text text="Panel 3" />
        </mx:VBox>
        <mx:VBox label="Green" width="100%" height="100%">
            <mx:Text text="Panel 4" />
        </mx:VBox>
        <mx:VBox label="Blue" width="100%" height="100%">
            <mx:Text text="Panel 5" />
        </mx:VBox>
    </mx:Accordion>

</s:Application>

And the custom Accordion header skin, CustomAccordionHeaderSkin.mxml, is as follows:

View skins/CustomAccordionHeaderSkin.mxml

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2009/06/21/creating-a-custom-halo-accordion-header-skin-in-flex-4/ -->
<s:SparkSkin name="CustomAccordionHeaderSkin"
        xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark"
        minWidth="21" minHeight="21"
        alpha.disabled="0.5">
    <!-- states -->
    <s:states>
        <s:State name="up" />
        <s:State name="over" />
        <s:State name="down" />
        <s:State name="disabled" />
        <s:State name="selectedUp" />
        <s:State name="selectedOver" />
        <s:State name="selectedDown" />
        <s:State name="selectedDisabled" />
    </s:states>

    <!-- layer 3: fill -->
    <s:Rect left="1" right="1" top="1" bottom="1">
        <s:fill>
            <s:SolidColor color="white"
                    color.up="red"
                    color.over="haloOrange"
                    color.down="yellow"
                    color.selectedUp="haloGreen"
                    color.selectedOver="haloBlue"
                    color.selectedDown="purple" />
        </s:fill>
    </s:Rect>

    <!-- layer 4: fill lowlight -->
    <s:Rect left="1" right="1" bottom="1" height="9">
        <s:fill>
            <s:LinearGradient rotation="90">
                <s:GradientEntry color="0x000000" alpha="0.0099" />
                <s:GradientEntry color="0x000000" alpha="0.0627" />
            </s:LinearGradient>
        </s:fill>
    </s:Rect>

    <!-- layer 5: fill highlight -->
    <s:Rect left="1" right="1" top="1" height="9">
        <s:fill>
            <s:SolidColor color="0xFFFFFF"
                        alpha="0.33"
                        alpha.over="0.22"
                        alpha.down="0.12" />
        </s:fill>
    </s:Rect>

    <!-- layer 6: highlight stroke (all states except down) -->
    <s:Rect left="1" right="1" top="1" bottom="1" excludeFrom="down">
        <s:stroke>
            <s:LinearGradientStroke rotation="90">
                <s:GradientEntry color="0xFFFFFF" alpha.over="0.22" />
                <s:GradientEntry color="0xD8D8D8" alpha.over="0.22" />
            </s:LinearGradientStroke>
        </s:stroke>
    </s:Rect>

    <!-- layer 6: highlight stroke (down state only) -->
    <s:Rect left="1" top="1" bottom="1" width="1" includeIn="down">
        <s:fill>
            <s:SolidColor color="0x000000" alpha="0.07" />
        </s:fill>
    </s:Rect>
    <s:Rect right="1" top="1" bottom="1" width="1" includeIn="down">
        <s:fill>
            <s:SolidColor color="0x000000" alpha="0.07" />
        </s:fill>
    </s:Rect>
    <s:Rect left="1" top="1" right="1" height="1" includeIn="down">
        <s:fill>
            <s:SolidColor color="0x000000" alpha="0.25" />
        </s:fill>
    </s:Rect>
    <s:Rect left="1" top="2" right="1" height="1" includeIn="down">
        <s:fill>
            <s:SolidColor color="0x000000" alpha="0.09" />
        </s:fill>
    </s:Rect>

    <!-- layer 2: border -->
    <s:Rect left="0" right="0" top="0" bottom="0" width="69" height="20">
        <s:stroke>
            <s:SolidColorStroke color="0x696969"
                        alpha="1"
                        alpha.over="1"
                        alpha.down="1" />
        </s:stroke>
    </s:Rect>

</s:SparkSkin>

This entry is based on a beta version of the Flex 4 SDK and therefore is very likely to change as development of the Flex SDK continues. The API can (and will) change causing examples to possibly not compile in newer versions of the Flex 4 SDK.

{ 5 comments… read them below or add one }

1 Ruy Adorno July 28, 2009 at 8:34 am

If there’s any other unfortunates like me browsing this page trying to get the Accordion skin to work well with the flex4, here comes a solution to set also a customized label skin:

First of all, set a creationComplete handler, in the skin class definition:
creationComplete=”onCreationComplete(event)”

After that, just add this script tag, with some magic code to get a reference of the original mx component:

After that you can access the properties of your original mx component like this:

This solution is just a complement to the article above, and is not a beautiful one. Hope that in the future someone come with a better and easier solution for this issue.

Reply

2 Ruy Adorno July 28, 2009 at 8:37 am

If there’s any other unfortunates like me browsing this page trying to get the Accordion skin to work well with the flex4, here comes a solution to set also a customized label skin:

First of all, set a creationComplete handler, in the skin class definition:
creationComplete=”onCreationComplete(event)”

After that, just add this script tag, with some magic code to get a reference of the original mx component:

After that you can access the properties of your original mx component like this:

This solution is just a complement to the article above, and is not a beautiful one. Hope that in the future someone come with a better and easier solution for this issue.

Reply

3 Ruy Adorno July 28, 2009 at 8:45 am

Shit, I can’t past the flex code here… the system keeps stripping my code….

This, should be placed inside a fx:Script tag….

import mx.events.FlexEvent;
 
[Bindable]
public var __parent:*;
 
protected function onCreationComplete(event:FlexEvent):void{
	//Get a reference to the "hostComponent", needed to be used like this 
	//because I couldn't make the metadata hostComponent work for the mx:VBox component
	__parent = this["parent"];
	//Hide the original label of flex component
	__parent.getChildAt(0).visible = false;
}

and after that you can use the __parent variable to access the information of the original mx component, just like the hostComponent should work…
In my example I set the first child to false, to hide the original label of mx component… then you should specify another label element and you can retrieve the string value like this:
text=”{__parent.label}”

Reply

4 Daniel October 19, 2009 at 10:40 am

If you want to make your header a flat gradient, and not use the highlights, my assumption would be that you could simple comment out the other fill layers and just use layer 3 (changing the gradient fill colors accordinly).

But when I do this, I get a strange shift in color where the colors look much darker than the values I’m putting in. This is probably my ignorance of the skinning framework (maybe the baseLayer attribute is somehow modifying the colors I enter).

Any thoughts on trying to do a flat gradient for the header.

As always, thanks for this immensely helpful site.

Daniel McQ

Reply

5 Daniel October 19, 2009 at 10:47 am

…and as usual the answer is pretty obvious on second glance: commenting out the

useBaseColor = true;

line allows level3 to show unmodified colors.

DMcQ

Reply

Leave a Comment

Sorry, this blog is terrible at eating HTML comments.
If you're pasting any HTML/XML/MXML code, you need to convert your < characters to &lt; and your > characters to &gt; .

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

Anti-Spam Protection by WP-SpamFree

Previous post: Setting the corner radius on the Halo Alert control in Flex 4

Next post: Setting the symbol color on the Spark DropDownList control in Flex 4