Advanced FXG Spark Icon Buttons with one generic skin in Flex4 (Gumbo)

June 20, 2009. Posted by Andy Hulstkamp under Actionscript 3 FXG Gumbo (Flex 4 beta)
Keywords: , , , , , , ,

For the past couple of days I’ve had a look at creating Spark Icon Buttons. In this post I’ve created an FXG Icon Button with some transitions, leveraging pseudo selectors for states. The Icon was ‘hardcoded’ into the skin. For another Icon I would need to duplicate the skin and introduce another graphic. Not exactly generic. There are other ways to bring graphics into Spark Skins but none of them work with FXG Elements directly.

What I want is:

  • work with FXG Graphic Elements for simpler manipulation and scaling
  • easily export the FXG-Definitions for the icons from a tool and/or be able to change them in FB directly
  • colorize the icons based on a color style-property and do this per state
  • change the icons based on a style-property and do this per state
  • change icons at runtime
  • scaling effect on icon
  • have ONE generic skin, so no duplicates for different icons are necessary

Most of the trouble with generic skins comes from the fact that there is no way to access the FXG Library-Definitions at run-time  (as far as I know) - like getting an instance of a symbol in the library, the way we had in flash. Here’s a hack but I’d rather not use it.

After some headaches I finally managed to get a solution I can live with:

Click here for a test.

You’ll find the source at the end of this post.

The solution regarding the work flow mainly comes down to

  • Create Icons in Illustrator and convert them to symbols. One symbol per icon, name them. Save from Illustrator as ai.
  • Load the Illustrator-File in Flash Catalyst and go to the Code-View
  • You’ll see that FC creates mxml-files with the graphical content per icon
  • Copy these files over to Flex-Builder or set the source path so that the catalyst export is in your flex project

In the code there are some key concepts:

  • In the skin there is a group where the icons will get attached at run time
  • The skin listens for state changes and creates an instance of an icon component based on the iconName that is passed via styles.
  • There is some caching involved, so that there will be no instantiation when an icon/state has allready been created
  • The Icons get colorized based on a style property and - if defined  - per state.
  • The colorization occurs recursively, diving through the nested elements and setting the color of any nested FilledElement
  • There is some code involved that manages the scaling of the new instances for the transitions
  • Icons, colors and baseColors can be set via styles (and using pseudo selectors for over and down states)

Here’s the source (sdk 4.0.0.7282)

Source updated to Flex 4 release sdk.

Note: As a variation to instantiate the icons you could put all the FXG-Definition in the Skin inside the library and create them at runtime using the hack mentioned at the beginning of this post.



Share/Save/Bookmark

28 Responses to “Advanced FXG Spark Icon Buttons with one generic skin in Flex4 (Gumbo)”

  1. Advanced FXG Spark Icon Buttons with one generic skin in Flex4 (Gumbo) | Web 2.0 Designer Says:

    [...] Original post: Advanced FXG Spark Icon Buttons with one generic skin in Flex4 (Gumbo) [...]

  2. AH: Spark Icon Button with Gradient effects and Filter animation, colorized by styles. Flex 4 (Gumbo) - Andy Hulstkamp. Seedlings for RIAs Says:

    [...] Check this example for a more advanced and generic [...]

  3. Flex 4 skinning ignores developer needs | Says:

    [...] noticed a number of people here (Andy McIntosh), and here (Andy Hulstkamp) working with button icon skins. The main reason for this is that Adobe saw fit to remove the icon [...]

  4. WS-Blog » Quick tip (Flex 4): Using generic skin classes Says:

    [...] “Advanced FXG Spark Icon Buttons with one generic skin in Flex4 (Gumbo)” by Andy Hulstkamp [...]

  5. Yarin Says:

    Huge! Thank you

  6. carmine Says:

    Andy, I am losing my mind here. Why can’t I do this:

    Why import graphics from catalyst if you can’t use them easily? This is a one time interaction for one project, I don’t need to skin! I will continue reading your examples, but if you have some quick enlightenment, it would be much appreciated.

  7. Andy Hulstkamp Says:

    Carmin

    I’m not sure if I know what you mean. If you don’t need to skin then you can simply use the default spark-buttons.

    The Spark-Button comes without an icon, so if you want one, then you would need to extend the component or the skin.

    If you don’t need a generic way to have your Icon-Buttons you can embedd the FXG-Definitions right into the skin (so you would have one - mostly duplicated - skin per Icon-Button). If you wan’t a more generic approach, you have to externalise the Icon-Graphic. I wanted to use FXG for this and this post looks into this.

    To add graphics you could also simply rely on bitmap-based images or vectors in a swf or swc like in flex 3. Have a look at this post .

    Now, Adobe has a clear dedication to FXG. The Flex 4 api and components are clearly laid out to use with FXG, the whole Product-Suite has FXG as a new Export-Format and Flash-Catalyst use FXG.

    Personally I like to have an editable vector-graphics format right in Flash-Builder. With FXG, once the Export is done, I can esily edit some aspects of the graphics right in the IDE - and using FXG gives me advantages when using some tags (transitions) or working with the graphics-api in Flex 4. That’s why I used the round-trip via FC (which gives me nice mxml-components with FXG that I can use right away.)

    Now, Flash-Catalyst and Flex 4 is not quite where I’d love it to be. I think we need a way to export FXG-Definitions to a library and load and access them at runtime. Adobe is not there yet, but I’m pretty sure that this will be added with priority in later versions.

    Even with this limitations I’m gonna use FXG wherever I can but I think it’s perfectly ok to use other formats if this suits the task.

    Does this answer your question?

  8. carmine Says:

    s:Button click=”button1_clickHandler(event)”
    s:BitmapImage id=”tete_coq” source=”@Embed(’/tete_coq.png’)” /
    /s:Button

    Sorry, the code in my last comment got eaten. Basically, why can’t I skin a button by putting a BitmapImage within its tags?

    I appreciate the explanation though. I want to use my psds and ais too! This skinning thing seems heavyhanded though.

  9. Nikos Says:

    wow so cool, thanks

  10. Flex 4 Skin – Links « iuricmp Says:

    [...] http://www.hulstkamp.com/2009/06/20/advanced-fxg-spark-icon-buttons-with-one-generic-skin-in-flex4-g... Deixe um Comentário [...]

  11. kevin Says:

    hi Andy,

    Do you know of a way to export a skin from Illustrator as FXG and import directly into FB4? Like we did with the design extensions for CS for MX components…

    I’ve been asking here but no-one has offered an answer yet:
    http://forums.adobe.com/message/2711627#2711627

  12. Andy Hulstkamp Says:

    Hi Kevin,

    Not that I know. AI CS5 might have such a feature but I guess Adobe will rather push Flash Catalyst for those kinds of things.

    andy

  13. Mark Says:

    wow, I am a rank beginner at this stuff, but I think this is an awesome piece of work — thanks a ton for sharing it!

  14. Mark Says:

    Andy,

    after looking deeper into your code I note your use of the namespace:

    xmlns:lib=”Haupt_library.*”

    I have googled this and only find similar instances in a couple googlecode projects.

    Can you tell me what this is, where to find it, and if it is indeed necessary?

    thanks, Mark

  15. Flex 4 — Reusable Icon Button Skins « Everything Under The Sun Says:

    [...] http://www.hulstkamp.com/2009/06/20/advanced-fxg-spark-icon-buttons-with-one-generic-skin-in-flex4-g... [...]

  16. Andy Hulstkamp Says:

    Mark,

    No, you don’t need this. It is an artifact that has been included when I exported the FXG-Icons from Catalyst.

    andy

  17. Mark Says:

    Andy,

    The following code works great:

    protected function toggleIcon(event:MouseEvent):void
    {
    var btn:Button = Button(event.currentTarget);
    if (iconCyclePtr >= iconCycle.length)
    {
    iconCyclePtr = 0;
    }
    btn.setStyle(”iconClass”, iconCycle[iconCyclePtr++]);
    }

    but when I try using it in an AIR app (i.e, a WindowedApplication) the following error is generated:

    Type 1046: Type was not found or was not a compile-time constant: Button.

    AS 3.0 Language and Components Reference further states:

    The class used as a type declaration is either unknown or is an expression that could have different values at run time. Check that you are importing the correct class and that its package location has not changed. Also, check that the package that contains the code (not the imported class) is defined correctly (for example, make sure to use proper ActionScript 3.0 package syntax, and not ActionScript 2.0 syntax).

    The error can also occur if the class being referenced is not defined in a namespace that is in use or is not defined as public:

    public class Foo{}

    ——————–

    I am still very much a newbie at all of this. Do you have any idea why this happens and how I might fix it?

    Many, many thanks in advance. I think your work is great!

    Mark

  18. Mark Says:

    p.s.

    I should have added that the following error is also generated:

    Type 1180: Call to a possibly undefined method Button.

    ???

  19. Andy Hulstkamp Says:

    Mark

    Make sure the sdk is included in the classpath and have a look at the updated components.

  20. Mark Says:

    Hi Andy,

    Again, thanks for all of your great posts!

    I have been implementing some of your techniques and am having trouble with one thing. I have some FXG files that have multiple colors in them. I have removed styling ( iconColor ) in hopes that this would allow the base colors of the FXG to show - no luck…

    Do you have any ideas on what might solve this?

    Many thanks,

    Mark

  21. Mark Says:

    Andy,

    w/r/t multiple colors…

    I got it!

    thanks,

    Mark

  22. Mark Says:

    Andy,

    I spoke too soon. Can you advise how I might use a source FXG file that will allow for fully colorized image?

    Again, many, many thanks.

    Mark

  23. Mark Says:

    OK! I got it. I removed the fillIconWithColor() and commented out the 2 references in the updateSymbol().

    thanks for your many great posts and ideas.

    Mark

  24. Nikos Says:

    Are there any librarys of mxml icons out there, I don’t have FC

  25. Andy Hulstkamp Says:

    Nikos

    Not that I know but you could use AI and export as FXG.

  26. Seraphin Says:

    Hello ! Thanks for your skin, it’s so pretty !
    I have an issue with a button used as defaultbutton of a form.
    When a field is focus, the button swith in emphasize mode, and the skin doesn’t seem to be compliant with that.

    How can i manage easily that ?
    I tried to add
    emphasized-skin: ClassReference(’skins.buttons.FXGIcon’); in my css, but nothing happened.
    Have you an idea ?

    Thanks a lot.

  27. Andy Hulstkamp Says:

    Seraphin

    Flex 4 uses the value in ‘emphasized’ to switch the styleName. If ‘emphasized’ is set to true, Flex will look for a styleName ‘emphasized’ and applies all the styles to the button.

    Thus using

    s|Button.emphasized {
    skinClass: ClassReference(’AHGenericFXGIconButtonSkin’);
    chromeColor: “0×00FF00″ ;
    color: #FFFFFF;
    iconColor: #e0e0e0;
    iconScale: 0.75;
    iconClass: ClassReference(”myLibrary.Bus”);
    color: “0xe0e0e0″;
    }

    will aplly all the values to the Button (Skin). Change them as needed.

    Actually I don’t know why the Flex SDK team did not decide to use the emphasize property as a state. But then again, you could easily introduce this to the component:

    Extend from Button override the emphasized property and change the behaviour so that a new state is being introduced. Then use this state in the skin to define a emphasized state.

    hth
    andy

  28. Seraphin Says:

    Thanks a lot, it works. ;-)

Leave a Reply