3

Anyone missed the old simple method for skinning a simple button?

<mx:Button x="10" y="10" label=""
           upSkin="@Embed('imgs/mainButton_std.png')"
           overSkin="@Embed('imgs/mainButton_over.png')"
           downSkin="@Embed('imgs/mainButton_over.png')"
           disabledSkin="@Embed('imgs/mainButton_std.png')"
           creationComplete="mainButtonHitArea()"
           width="75" height="75" id="menuButton" enabled="true"/>
//mainButtonHitArea() : Is a generic function that generates the hit area

The problem im having is that, this method of creating a simple button with skin is being phased out : Infact it is no longer supported in flex 4.5 mobile projects.

So the question: Is there a simple way to perform this, with spark buttons (which is suppose to be the new way to go). As simple as possible.

Basically i only need a button with 2 images : down/over & up. And i want to keep the code as simple as possible : The new skinning methods, seems to really adds way too much lines for something that used to be as simple as the example above.

PicoCreator
  • 9,886
  • 7
  • 43
  • 64

3 Answers3

12

You can create a skin, i.e. (as MyButtonSkin.mxml):

<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin name="MyButtonSkin"
             xmlns:fx="http://ns.adobe.com/mxml/2009" 
             xmlns:s="library://ns.adobe.com/flex/spark" 
             xmlns:fb="http://ns.adobe.com/flashbuilder/2009">
    <s:states>
        <s:State name="up" />
        <s:State name="over" />
        <s:State name="down" />
        <s:State name="disabled" />
    </s:states>    
    <fx:Metadata>
        <![CDATA[
        [HostComponent("spark.components.Button")]
        ]]>
    </fx:Metadata>    
    <s:BitmapImage source.disabled="@Embed('assets/image1.png')" 
                source.down="@Embed('assets/image2.png')" 
                source.up="@Embed('assets/image3.png')" 
                source.over="@Embed('assets/image4.png')" />
</s:SparkSkin>

Then you can assign that skin to some button:

<s:Button skinClass="MyButtonSkin"/>
  • >.< i was hopping for a simpler solution though, sadly... But i may take this, if there is truely no other answer. – PicoCreator Jun 25 '11 at 11:01
  • 2
    I remember having this same feeling of annoyance when I couldn't simply assign images to button states. OTOH, using skinning opens the door to more powerful stuff. What I posted is obviously just a bare-down skin. –  Jun 25 '11 at 11:05
  • 1
    agreed, that it really open doors, especially animated buttons. or those really custom ones... Just annoyed that it is a much bigger overhead when its not needed though =( – PicoCreator Jun 25 '11 at 11:21
  • 1
    Overhead? Actually, the overhead of this is smaller than the one in the mx button. You have to remember that you now have a separate file which can be reused as you please and doesn't need to load any extras. From there, you just need to set the skin on each button that you want the image. Makes very good use of reusability instead of copying that skin code all over the place which would be annoying to update if you ever needed to. – J_A_X Jun 28 '11 at 13:38
8

Here's a basic image button that's more general:

ImageButtonSkin.mxml

<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">
    <fx:Metadata>
        [HostComponent("com.instantdelay.flex.commons.ImageSkinnableButton")]
    </fx:Metadata>
    <s:states>
        <s:State name="up" />
        <s:State name="over" />
        <s:State name="down" />
        <s:State name="disabled" />
    </s:states>
    <s:BitmapImage id="image"
                   source.up="{getStyle('upImage')}"
                   source.down="{getStyle('downImage')}"
                   source.over="{getStyle('overImage')}"
                   source.disabled="{getStyle('disabledImage')}"
                   />
</s:SparkButtonSkin>

ImageSkinnableButton.as

[Style(name="upImage", inherit="no", type="Class")]
[Style(name="downImage", inherit="no", type="Class")]
[Style(name="overImage", inherit="no", type="Class")]
[Style(name="disabledImage", inherit="no", type="Class")]
public class ImageSkinnableButton extends Button
{
    public function ImageSkinnableButton()
    {
        super();
        setStyle("skinClass", ImageButtonSkin);
    }
}

Then you can set the images as styles on the button in either CSS (preferred) or in mxml:

<commons:ImageSkinnableButton
    upImage="@Embed('imgs/mainButton_std.png')"
    overImage="@Embed('imgs/mainButton_over.png')"
    downImage="@Embed('imgs/mainButton_over.png')"
    disabledImage="@Embed('imgs/mainButton_std.png')" />
takteek
  • 7,020
  • 2
  • 39
  • 70
  • Yes ultimately you need to create something like this if you have to skin more than one button. –  Jun 25 '11 at 11:44
  • How can I use a symbol from a swc lib as the `up/over/down/disabledImage` ? Which container should I use in `ImageButtonSkin` (you are using `s:BitmapImage`) ? – Peter Lee Dec 14 '12 at 22:48
  • @takteek This was a-w-e-s-o-m-e-! – abnvp Dec 14 '13 at 09:26
5

You can also define a ButtonImageSkin for the default spark.components.Button component, for example in the imageskins package:

<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">
    <fx:Metadata>
        [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:BitmapImage source="{getStyle('backgroundImage')}"/>
</s:SparkButtonSkin>

Simply define a style on the skin class itself, and bind the source of the image to it. Now, you can control the actual images using CSS pseudo selectors:

@namespace imageskins "imageskins.*";
s|Button {
    skinClass: ClassReference("imageskins.ButtonImageSkin");    
}
imageskins|ButtonImageSkin:up {
    backgroundImage: Embed(source="assets/images/button-up.png");
}
imageskins|ButtonImageSkin:down {
    backgroundImage: Embed(source="assets/images/button-down.png");
}
imageskins|ButtonImageSkin:over {
    backgroundImage: Embed(source="assets/images/button-over.png");
}
imageskins|ButtonImageSkin:disabled {
    backgroundImage: Embed(source="assets/images/button-disabled.png");
}

This way you can obtain the result with more flexible CSS based rules. I ended up creating a set of image-based Spark skins for various Flex components: FXG is way more powerful, but sometimes working with scale9 images is simply the quickest way to obtain the desired result.

Side note: if you put your skin classes and your CSS file (with any name) in a Flex Library Project, and compile your client project with the -theme option, Flex will automatically apply the CSS.. useful when creating a set of skin along with the CSS that associate them with their host components.