Flex/Flash/Actionscript

Nifty Flex Accordion Menu (like on Apple.com)

This is an example of using a slightly modified Flex Accordion to create a sweet looking menu. Someone on flexcoders asked how to make a menu like the one found here on Apple’s website.

Here’s the example I came up with to do this:

This movie requires Flash Player 9.

The Accordion
This is a Flex Accordion component (well, sort of…). It’s actually a slightly modified Accordion. The cool part is that FlexLib already had a modified Accordion component because I had made the Horizontal Accordion. Because of that there has been a VAccordion in FlexLib as well, which up until now has been exactly the same as the normal Accordion component in the framework.

So I added a new property to both VAccordion and HAccordion called headerLocation, which allows you to specify where the header should appear relative to the content. For VAccordion this property can be either “above” or “below”. Using above means it works just like the normal Accordion. But now you can also specify below, which will render the header below the content, which was the first requirement for this example.

The header renderer
The next problem was that the header of the Accordion needs to be more complex than a normal button. It needs to show two text fields, one for the title of the header and one for the descriptive text. And the description needs to wrap on multiple lines. So as I blogged about previously, I used the CanvasButtonAccordionHeader in FlexLib to easily use a complex header on an Accordion.

The header skin
Next we have the problem of the skin for the button. The skin isn’t too complex, but there are a few things that are hard to do with the standard Button skin. We want rounded corners on the bottom of the button but not the top. And we want nice control over the gradient of the button. What to do? FlexLib has an EnhancedButtonSkin that lets us do all this (and a lot more). Problem solved.

The mouse interaction
The menu we’re trying to emulate responds to mouse over events, not clicks like the normal Accordion does. This is easy enough to fix by simply faking a MouseEvent.CLICK event any time we get a MouseEvent.MOUSE_OVER event. By making our headers dispatch these fake click events we trick the Accordion into opening the child when the mouse rolls over each header.

And there you have it.

View the example in its own window (view-source enabled)
View the source of the example

In the source I’ve bundled a version of flexlib.swc that includes the new headerLocation property for the Accordion components. This is because I haven’t yet released an updated distribution zip on the FlexLib project page that includes this update (but I did commit the changes to SVN if you’re using that).

Standard

73 thoughts on “Nifty Flex Accordion Menu (like on Apple.com)

  1. Greg says:

    I did an “auto-opening” accordion a while back, but I did it by setting a mouseover event handler on each header that set the Accordion’s selectedIndex (rather than simuating the mouse click). Is there any advantage of one way over the other?

  2. Doug – very well done. I have a project where I want to get this effect:

    http://www.savuti.com/examples/CMenuAS3.swf

    I have done this in Flash using timeline animation. I now need it in Flex. It seems the easiest way to do this is to have each header width controlled individually. At the moment, all header widths are controlled together with the paddingTop property. Any suggestions on how to control the header widths individually (or any other suggestions on hoe to accomplish this) will be highly appreciated. Thank you in advance.

  3. Doug – Thank you for the contributions you’ve made to the community through FlexLib and your blog. I’m sure you’ve helped a lot of people improve their Flex/AS3 skills.

    I did want to get your take on the best way to go about developing a component that integrates the functionality of the tree control with the scrollable menu component you did.

    Essentially, I’d like a build a menu that is recursive like a tree/menu but when opening a branch that contains more children than can be displayed in the available space, a control like your scrollable menu would appear. This would give the user the ability to navigate to all nodes by either hovering over the “down arrow” or via detecting the mouse position. The main difference between the control I would like to build and your scrollable menu is that I don’t want to popUp the child menu but rather, move the next parent node(s) down as far as possible in the available space, and scroll the “leaf” nodes via mouse position or up/down arrows on a layer below the parent displayObjects.

    Unlike the Tree control which displays a scrollbar for the entire tree, the component I’d like to develop, would only scroll the level of nodes the user is interacting with.

    I could possibly do something similar by cascading containers and lists, but that seems aweful ugly to me and having a control like this wrapped up into a nice tidy component would pretty sweet.

    Here’s an example of a component I wrote for AS2 which shows the functionality I’d pretty much like to recreate. This component goes bottom-up, but has a flag to switch to top-down which I’d like to add at some point, but top-down would be fine as a starting point! This version does not show the scrolling feature, so I hope my above description makes sense.

    useflashmore.com/accordion-menu-example

    I really think a control like this for Flex would be pretty sweet and I’d love to post it to flexlib if I can pull it off!

    Sorry for the length of this post.

  4. Duane Hardy says:

    I am trying to recreate the mouseover effect with no luck in my accordian. I have a repeater that builds the accordian from xml. What should I be doing differently?

  5. Doug, I just wanted to thank you for all the source you’ve released on flexlib. I finally got my component working and I couldn’t have done it without studying everything you’ve done. You really write some nice code man! (man that reads a lot more dorky than intended).

    I’d love to get your thoughts on what I’ve got going if you get a chance.

    Here’s the link to the working example for the
    Scrollable Accordion Style Custom Component

    Here’s the full URL if above href doesn’t go through:
    http://www.useflashmore.com/flex-as3-scrollable-accordion-menu/scrollable-accordion-menu-custom-component/main.html

    Best regards and thanks.
    Justin Winter – useflashmore.com

  6. Pingback: Freelance Jobs - Freelance Gigs » Flash Acordion Menu by pauld581

  7. Pingback: https-chase.com » Blog Archive » Flash Acordion Menu by pauld581

  8. kevin says:

    Is the CanvasButtonAccordionHeader compatible with Fle 3 Beta 3? I have had trouble getting it to compile in the nightly build I am using (form 12/22/07).

  9. Ralph Krausse says:

    I am getting the same prob with Beta 3. Here are the errors…

    Severity and Description Path Resource Location Creation Time Id
    1044: Interface method get creatingContentPane in namespace mx.core:IContainer not implemented by class Controls.Menu:Header. GMN/src/Controls/Menu Header.mxml line 7 1201788079359 72
    1044: Interface method get defaultButton in namespace mx.core:IContainer not implemented by class Controls.Menu:Header. GMN/src/Controls/Menu Header.mxml line 7 1201788079375 76
    1044: Interface method get horizontalScrollPosition in namespace mx.core:IContainer not implemented by class Controls.Menu:Header. GMN/src/Controls/Menu Header.mxml line 7 1201788079375 78
    1044: Interface method get verticalScrollPosition in namespace mx.core:IContainer not implemented by class Controls.Menu:Header. GMN/src/Controls/Menu Header.mxml line 7 1201788079375 74
    1044: Interface method get viewMetrics in namespace mx.core:IContainer not implemented by class Controls.Menu:Header. GMN/src/Controls/Menu Header.mxml line 7 1201788079375 79
    1044: Interface method set creatingContentPane in namespace mx.core:IContainer not implemented by class Controls.Menu:Header. GMN/src/Controls/Menu Header.mxml line 7 1201788079359 71
    1044: Interface method set defaultButton in namespace mx.core:IContainer not implemented by class Controls.Menu:Header. GMN/src/Controls/Menu Header.mxml line 7 1201788079359 73
    1044: Interface method set horizontalScrollPosition in namespace mx.core:IContainer not implemented by class Controls.Menu:Header. GMN/src/Controls/Menu Header.mxml line 7 1201788079375 75
    1044: Interface method set verticalScrollPosition in namespace mx.core:IContainer not implemented by class Controls.Menu:Header. GMN/src/Controls/Menu Header.mxml line 7 1201788079375 77

  10. yo says:

    Hi ,
    You are don! I tried to download and run the source, but got error “could not resolve to a component “. What may be wrong?

  11. yo says:

    Sorry It was beacuse of fb3( & i forgot to add swc in library path ) , it runs fine in fb2. Now I am trying to add images at runtime. The added item is selected. It works Ok but problem is that when i add new AccordionItem at first time half of the image is cut. When you select diffrerent item, it becomes ok, but at the initall time of addition it is half cut. What is solution ?

    This is teh code i am adding to main ( AppleAccordionExample ) mxml file

  12. Ed says:

    This is very good!…I was changing the text box for a textarea to get the scrolling bar when text is long, but the scrolling doesn’t work, any idea why?

  13. doug says:

    Please do not flame me for asking, but I am ignorant about this flex stuff. I downloaded the file and got it running looking like just on this site, but when I change the info in the mxml file, it does not update the menu. Does this have something to do with the swf file? I was thinking this thing could be modified in xml like other flash type menus. Any assistance with this is appreciated. Thanks!

  14. jastero says:

    Is it possible to preload the images so that the first time you roll over the different items, there is a smooth transition? If you notice, the images kinda pop in the first time, then when you roll back over them, they seem to be cached or something. I am trying to do this on a project using the accordion, but with no luck yet. The client is really crazy about transisitions, so it is a problem for me.

    Thanks!

  15. Scott Macdonald says:

    I am getting this error in Header.mxml:

    Severity and Description Path Resource Location Creation Time Id
    1044: Interface method get creatingContentPane in namespace mx.core:IContainer not implemented by class Header. LiveDocTrackerProject/src Header.mxml line 7 1223063665991 209

    I am using Flex 3.

  16. Erich Cervantez says:

    This is great, Doug, thanks for the article.

    I have a simple question, though, for you or anyone else out there in flex-land: what’s a simple or not-so-simple way of defaulting the Accordian to a “closed” state initially? In other words, I’d like for none of the child containers to display until a user clicks a header.

  17. Kevin says:

    Awesome menu.

    I’m trying to create a horizontal version, which is going well except for one problem. I can’t get any text to display on the header. Other components will render, such as a button, but the button renders without the label. Any idea what could be wrong?

  18. Tom says:

    Guys, Flex is open source! If you want to replace the AccordionHeader by a HBox (instead of the classic button) is really easy! You just create a CustomAccordion, copy/paste the Adobe Accordion sources and replace Button every where by HBox. Takes 10 secondes! And you have the accordion you want!

    Is someone has an idea why Adobe dev team has fixed the headeritemrenderer class as a Button instead of a UIComponent or an interface such as IAccordionHeader?

  19. Tito says:

    1) Problem with interface: I’ve got the new flexlib.swc there http://code.google.com/p/flexlib
    2) Now i want to solve the problem with data.title , a message says that a data binding will not be detected. How can i change the content ?
    Thanks,
    from a flex beginner.

  20. Pingback: 110+ Awesome Resources for Popular Adobe Products | Spoonfed Design

  21. Pingback: 110+ Awesome Resources for Popular Adobe Products | Spoonfed Design

  22. Daniel says:

    I was able to load your example perfectly fine in my project, but the problem is that when I move the mouse over the panels, they aren’t smooth transition effects like yours and are very jumpy.

    Also, when you move your mouse quickly over the accordion panels (doesn’t happen on yours), the main panel (where is says “Essentials”) suddenly disappears and then reappears.

    (on FB3 with most recent flexlib.swc

    Any ideas?

    Thanks!

  23. quantum says:

    hello everybody !

    for this marvellous component (thx Doug!) to work with flex3:

    – get the latest flexlib
    – in AppleAccordionExample.mxml, change to
    – in Header.mxml, change rollOverEffect=”fakeMouseClick( event )” to mouseOver=”fakeMouseClick( event )”

    sorry for the databinding warnings, I didn’t find out why this happens, but it works anyway…
    by trying this.data.title, the code completion finds “data”…

    have a good day

  24. quantum says:

    in AppleAccordionExample.mxml, change “flexlib:VAccordion” to “containers:VAccordion”

  25. quantum says:

    then finally to get rid of the binding warnings :

    create a function and call it in the creationComplete event of the VBox

    private function getText():void
    {
    lbl.text = this.data.title;
    txt.text = this.data.description;
    }

    [

    ]

  26. quantum says:

    and remove these :

    text=”{this.data.title}”
    text=”{this.data.description}”

    from the Label and Text tag to which you gave an id

    :-)

  27. Daniel says:

    @quantum: thanks for the help on this…im just not sure about what you mean with changing “flexlib:VAccordion” to “containers:VAccordion”…would you then declare containers as a bindable source (xmlns:flexlib=”http://code.google.com/p/flexlib/” changed to what?)

    thanks.

  28. quantum says:

    flexlib:VAccordion is the main tag, under the Panel, I put it in quotes because this input text don’t take the entry tag sign( “left arrow”, I don’t know how you call this key in english).

    I also don’t use the .swc but the folders with classes, in properties -> Flex Build PAth -> Source Path

    so when you open a tag and type VAcco… the code completion gives you the right one, and xmlns:containers=”flexlib.containers.*” is automatically added.

  29. Hey

    I am having the same problem I could not render this one in horizontal way – the label seems to be showing up empty.

    Could someone show how to use this nifty vertical accordion to show up as horizontal?

    Thanks

  30. Jeroen says:

    Hey,

    Could someone upload a working zip-file with the whole project and libraries needed to let this work in Flex Builder 3. I’ve been trying to get it to work, download new flexlib and such, but I keep getting these errors:

    – 1046: Type was not found or was not a compile-time constant. VAccordion.
    – Could not resolve to a component implementation. (for each item)

    a bit of my code:

    I have a flexlib folder in the root of my projectfolder with all the classes and such I downloaded from the flexlib website.

    Thanks

  31. Raghu says:

    Hi ,
    i am getting this error when i am trying to execute download files

    Could not resolve to a component implementation.
    how can i resolve this

    Thanks
    Raghu

  32. J0se says:

    U have to put the .swc file in the libs directory, then have your own images to replace or get those ones.

    cheers

  33. Jeffrey says:

    I kept getting this
    The prefix “containers” for element “containers:VAccordion” is not bound.

    no idea how to solve it.

  34. Philip says:

    @Erich Cervantez –
    I had the same question about how to make all of the children hidden when the accordion first displays. I ended up using the following solution:
    1. Use id.getHeaderAt(menu.numChildren-1).setVisible(false);
    2. id.selectedIndex = id.numChildren-1;

    and then just create an empty child container of the accordion as the last child. The two lines above will hide the last child, and then select it so it appears that all of the children are closed

  35. DK says:

    Guys,
    A little help please. I have done what I thought were all the right steps to getting the library path to work for the component to render. It will sporadically display in design view, but never when the project is run. The screen turns the default blue and all I get get is a blue screen on my browser, then the design view turns all blue. What is going on? I’m using 3.3…
    here’s what I did:
    -. get the swc 2.4
    -put swc in lib folder (i tried libs too, still not working)/set the path in properties
    -mimic the doug mccune VAccordian example with the two components and then calling it out in the main app. —> then blue screen.

    A little insight on this would help me sleep better at night…
    Thanks

  36. Kambeez says:

    hi Doug,

    It is fantastic. I couldn’t trust my eyes, lookign at your cool stuff.
    We are going to use your component for presenting a research project of a german university of Duisburg-Essen.
    Everybody here would like to say thank you and appreciate for your contribution.
    It was a relief for us, as we were struggling with CSS stuff to mak a nice website.

    cheers,

    the website design-team of research project

  37. Stelish says:

    Hi Doug

    Man this is awesome, but i can’t get it to work with Flex Builder 3, and it’s hacking me off.

    I know you get this alot, but you are no doubt “the man”, i got the following error when trying to complile the app:
    Could not resolve to a component implementation.

    Here’s my mxml:

    Application {
    backgroundGradientColors: #FFFFFF, #FFFFFF;
    backgroundGradientAlphas: 1, 1;
    vertical-align: middle;
    horizontal-align: center;
    }

    VAccordion {
    headerHeight: 80;
    vertical-gap: 5;
    background-alpha:0;
    open-duration:500;
    border-style:none;
    padding-bottom:5;
    header-style-name: gradientHeader;
    }

    .gradientHeader {
    upSkin:ClassReference(‘flexlib.skins.EnhancedButtonSkin’);
    overSkin:ClassReference(‘flexlib.skins.EnhancedButtonSkin’);
    downSkin:ClassReference(‘flexlib.skins.EnhancedButtonSkin’);
    disabledSkin:ClassReference(‘flexlib.skins.EnhancedButtonSkin’);
    selectedUpSkin:ClassReference(‘flexlib.skins.EnhancedButtonSkin’);
    selectedOverSkin:ClassReference(‘flexlib.skins.EnhancedButtonSkin’);
    selectedDownSkin:ClassReference(‘flexlib.skins.EnhancedButtonSkin’);
    selectedDisabledSkin:ClassReference(‘flexlib.skins.EnhancedButtonSkin’);
    font-family:Arial;
    cornerRadii: 0, 0, 10, 10;
    borderColors: #FFFFFF, #FFFFFF;
    overBorderColors: #FFFFFF, #FFFFFF;
    selectedBorderColors: #FFFFFF, #FFFFFF;
    borderThickness: 2;
    borderAlpha: 1;
    fillColors: #FFFFFF, #FFFFFF;
    fillAlphas: 1, 1;
    fillColorRatios: 0, 255;
    overFillColors: #FFFFFF, #BAC2CF;
    overFillAlphas: 1, 1;
    overFillColorRatios: 0, 169;
    selectedFillColors: #FFFFFF, #BAC2CF;
    selectedFillAlphas: 1,1;
    selectedFillColorRatios: 0, 169;
    }

    Panel {
    borderStyle: solid;
    borderColor: #b7babc;
    corner-radius:10;
    borderAlpha: 1;
    roundedBottomCorners: true;
    headerHeight: 24;
    highlightAlphas: 0, 0;
    headerColors: #b1b7c4, #8392ab;

    titleStyleName: “mypanelTitle”;
    border-thickness-left:1;
    border-thickness-right:1;
    border-thickness-top:0;
    border-thickness-bottom:-5;

    border-thickness:1;
    }

    .mypanelTitle {
    color: #ffffff;
    fontSize: 12;
    }

    Not using the flexlib.swc, but using flexlib folder like “quantum” recommended, but still get this error.

    Any ideas??, please help, i’m going crazy………

    Regards

  38. Stelish says:

    Sorry here’s the full mxml:

    Application {
    backgroundGradientColors: #FFFFFF, #FFFFFF;
    backgroundGradientAlphas: 1, 1;
    vertical-align: middle;
    horizontal-align: center;
    }

    VAccordion {
    headerHeight: 80;
    vertical-gap: 5;
    background-alpha:0;
    open-duration:500;
    border-style:none;
    padding-bottom:5;
    header-style-name: gradientHeader;
    }

    .gradientHeader {
    upSkin:ClassReference(‘flexlib.skins.EnhancedButtonSkin’);
    overSkin:ClassReference(‘flexlib.skins.EnhancedButtonSkin’);
    downSkin:ClassReference(‘flexlib.skins.EnhancedButtonSkin’);
    disabledSkin:ClassReference(‘flexlib.skins.EnhancedButtonSkin’);
    selectedUpSkin:ClassReference(‘flexlib.skins.EnhancedButtonSkin’);
    selectedOverSkin:ClassReference(‘flexlib.skins.EnhancedButtonSkin’);
    selectedDownSkin:ClassReference(‘flexlib.skins.EnhancedButtonSkin’);
    selectedDisabledSkin:ClassReference(‘flexlib.skins.EnhancedButtonSkin’);
    font-family:Arial;
    cornerRadii: 0, 0, 10, 10;
    borderColors: #FFFFFF, #FFFFFF;
    overBorderColors: #FFFFFF, #FFFFFF;
    selectedBorderColors: #FFFFFF, #FFFFFF;
    borderThickness: 2;
    borderAlpha: 1;
    fillColors: #FFFFFF, #FFFFFF;
    fillAlphas: 1, 1;
    fillColorRatios: 0, 255;
    overFillColors: #FFFFFF, #BAC2CF;
    overFillAlphas: 1, 1;
    overFillColorRatios: 0, 169;
    selectedFillColors: #FFFFFF, #BAC2CF;
    selectedFillAlphas: 1,1;
    selectedFillColorRatios: 0, 169;
    }

    Panel {
    borderStyle: solid;
    borderColor: #b7babc;
    corner-radius:10;
    borderAlpha: 1;
    roundedBottomCorners: true;
    headerHeight: 24;
    highlightAlphas: 0, 0;
    headerColors: #b1b7c4, #8392ab;

    titleStyleName: “mypanelTitle”;
    border-thickness-left:1;
    border-thickness-right:1;
    border-thickness-top:0;
    border-thickness-bottom:-5;

    border-thickness:1;
    }

    .mypanelTitle {
    color: #ffffff;
    fontSize: 12;
    }

  39. ThaStyle says:

    very very nice been playing with it alot thanks doug
    Steli… be sure to put the flexlib in the declaration i’m using the latest flexlib svn as folder not swc..
    (my accordion is located in nl.thastyle.webshop.content.panel (in this folder is also the header and the accordion item…

    xmlns = “nl.thastyle.webshop.content.panel.*”
    xmlns:mx = “http://www.adobe.com/2006/mxml”
    xmlns:flexlib = “http://code.google.com/p/flexlib/”

  40. Iztok says:

    can someone please explane me if it is possible to import this in iweb and how? I would die to have this on my page ;)

    ty

    Iztok

  41. Ryan says:

    I’ve got it working great in FB3. It took me a second to figure out the data binding fix, but other than that, flawless. You are the man.

  42. aesbus says:

    NICE! i finally got it working in flex builder 3…

    AND

    Got it working in visual studio 2008 with tofino.

    Im a newbie to flex, but programming for 20 years.

    hit me up anyone if i can be of any assistance.

    aesbus@gmail.com

  43. William says:

    @ Ryan, aesbus,

    Would you please explain how you got it working in Flex Builder 3, i am still getting this error -> Could not resolve to a component implementation.

    comp is a namespace i created for components
    xmlns:comp=”com.components.*”

    and i put the AccordionItem.mxml file in com.components

  44. William says:

    used source not SWC and nogettg this error
    Could not resolve containers:VAccordion to a component implementation.

  45. William says:

    used source not SWC and now getting this error
    Could not resolve containers:VAccordion to a component implementation.

  46. Pingback: AS 3.0 ACCORDION EFFECT « things to remember

  47. Ed Melendez says:

    Hi Doug,
    I’m having trouble implementing this on my site.
    can you send me a package with everything I need to get it to work?

    Appreciated.

    Thanks
    Ed

  48. Pingback: - ????Accordion??-It??-Freddie's Ria World | Freddie's Ria World

  49. NewToFlex says:

    Hi Doug,
    I was wondering if there is flex 4 version of your flexlib?
    I imported your Accordion sample and I get some compilation errors.
    Thanks

  50. Looks neat indeed, but compiling in FDT 4 with Flex 3.5 SDK produces an error:
    …src/Header.mxml[7]:
    Interface method get viewMetrics in namespace mx.core:IContainer not implemented by class Header.

    mouseOver="fakeMouseClick(event)">
    ^

  51. Sahib says:

    am getting error, Could not resolve to a component implementation!
    Could any one please attached the zip format of whole project with SWC for FB3?
    Many thanks in advance

    Regards
    Sahib

  52. Sahib says:

    @ quantum, i followed ur instruction , the previous error Could not resolve to a component implementation! ha been sorted out. Thanks
    Not am getting this error The prefix “containers” for element “containers:VAccordion” is not bound.
    Please provide your suggestion on this.
    Much Appriciated

    Regards,
    Sahib

  53. Sahib says:

    @ quantum, i followed ur instruction , the previous error : Could not resolve to a component implementation! has been sorted out. Thanks
    Now am getting this error The prefix “containers” for element “containers:VAccordion” is not bound.
    Please provide your suggestion on this.
    Much Appriciated

    Regards,
    Sahib

  54. Magician says:

    Guys > I tried to run it on Flex 4 (Flash Builder 4), included the path to flexlib.swc but got an error 1046: Type was not found or was not a compile-time constant: RoundedRectangle.

    Pls any suggestions to resolve this. :(

  55. Eugen says:

    For Flex 4:
    Download latest version flexlib for Flex 4 and unzip in AppleAccordionExample folder (AppleAccordionExample/flexlib).
    Now open Terminal and get to AppleAccordionExample folder (cd AppleAccordionExample).
    Now compile to SWF file: “mxmlc -library-path+=flexlib4/flexlib.swc -define+=FLEX_TARGET_VERSION::flex4,true -define+=FLEX_TARGET_VERSION::flex3,false AppleAccordionExample4.mxml”

  56. Eugen says:

    Yoopi :D i have it !!
    1. fixed all errors in css style for Flex 4
    2. changed code from static to dynamic content: AS3 create dynamic AccordionItems, load images and content in AccordionItems and change menu width from XML.
    3. SWF file have only 55kb

Comments are closed.