08
Sep
08

Extending the LinkButton control in Flex

The following example shows how you can extend the Flex LinkButton control and add your own custom styles to a custom skin class.

Full code after the jump.

View MXML

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2008/09/08/extending-the-linkbutton-control-in-flex/ -->
<mx:Application name="LinkButton_skin_test"
        xmlns:mx="http://www.adobe.com/2006/mxml"
        xmlns:comps="comps.*"
        layout="vertical"
        verticalAlign="middle"
        backgroundColor="white">

    <mx:ApplicationControlBar dock="true">
        <mx:Form styleName="plain">
            <mx:FormItem label="enabled:">
                <mx:CheckBox id="checkBox" selected="true" />
            </mx:FormItem>
        </mx:Form>
    </mx:ApplicationControlBar>

    <comps:CustomLinkButton1 id="linkButtonMXML"
            label="LinkButton (MXML)"
            toggle="true"
            enabled="{checkBox.selected}"
            skin="skins.CustomLinkButtonSkin1"
            rollOverColor="red"
            selectionColor="haloOrange"
            toggleBackgroundColor="yellow" />

    <comps:CustomLinkButton2 id="linkButtonAS"
            label="LinkButton (ActionScript)"
            toggle="true"
            enabled="{checkBox.selected}"
            skin="skins.CustomLinkButtonSkin1"
            rollOverColor="red"
            selectionColor="haloOrange"
            toggleBackgroundColor="yellow" />

</mx:Application>

comps/CustomLinkButton1.mxml

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2008/09/08/extending-the-linkbutton-control-in-flex/ -->
<mx:LinkButton xmlns:mx="http://www.adobe.com/2006/mxml">

    <mx:Metadata>
        [Style(name="toggleBackgroundColor",
                type="uint",
                format="Color",
                inherit="yes")]
    </mx:Metadata>

    <mx:Script>
        <![CDATA[
            override public function set enabled(value:Boolean):void {
                super.enabled = value;
                useHandCursor = value;
            }
        ]]>
    </mx:Script>

</mx:LinkButton>

comps/CustomLinkButton2.as

/**
 * http://blog.flexexamples.com/2008/09/08/extending-the-linkbutton-control-in-flex/
 */
package comps {
    import mx.controls.LinkButton;

    [Style(name="toggleBackgroundColor",
            type="uint",
            format="Color",
            inherit="yes")]

    public class CustomLinkButton2 extends LinkButton {
        public function CustomLinkButton2() {
            super();
        }

        override public function set enabled(value:Boolean):void {
            super.enabled = value;
            useHandCursor = value;
        }
    }
}

skins/CustomLinkButtonSkin1.as

/**
 * http://blog.flexexamples.com/2008/09/08/extending-the-linkbutton-control-in-flex/
 */
package skins {
    import mx.skins.halo.LinkButtonSkin;
    import mx.styles.StyleManager;

    public class CustomLinkButtonSkin1 extends LinkButtonSkin {
        public function CustomLinkButtonSkin1() {
            super();
        }
        override protected function updateDisplayList(w:Number, h:Number):void {
            super.updateDisplayList(w, h);

            // Inherited styles
            var cornerRadius:Number = getStyle("cornerRadius");
            var rollOverColor:uint = getStyle("rollOverColor");
            var selectionColor:uint = getStyle("selectionColor");

            // Custom styles
            var toggleBackgroundColor:uint = getStyle("toggleBackgroundColor") || getStyle("themeColor");

            graphics.clear();

            switch (name) {
                case "upSkin":
                    // Draw invisible shape so we have a hit area.
                    drawRoundRect(
                            0,                /* x */
                            0,                /* y */
                            w,                /* width */
                            h,                /* height */
                            cornerRadius,    /* cornerRadius */
                            0,                /* color */
                            0.0                /* alpha */
                        );
                    break;

                case "selectedUpSkin":
                case "selectedOverSkin":
                    drawRoundRect(0, 0, w, h, cornerRadius, toggleBackgroundColor, 1.0);
                    break;

                case "overSkin":
                    drawRoundRect(0, 0, w, h, cornerRadius, rollOverColor, 1.0);
                    break;

                case "selectedDownSkin":
                case "downSkin":
                    drawRoundRect(0, 0, w, h, cornerRadius, selectionColor, 1.0);
                    break;

                case "selectedDisabledSkin":
                    // Draw 20% alpha shape so we have a hit area.
                    drawRoundRect(0, 0, w, h, cornerRadius, toggleBackgroundColor, 0.2);
                    break;

                case "disabledSkin":
                    // Draw invisible shape so we have a hit area.
                    drawRoundRect( 0, 0, w, h, cornerRadius, 0, 0.0);
                    break;
            }
        }
    }
}

View source is enabled in the following example.

You can also specify the custom skin class in an external .CSS file or <mx:Style /> block, as seen in the following example:

View MXML

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2008/09/08/extending-the-linkbutton-control-in-flex/ -->
<mx:Application name="LinkButton_skin_test"
        xmlns:mx="http://www.adobe.com/2006/mxml"
        xmlns:comps="comps.*"
        layout="vertical"
        verticalAlign="middle"
        backgroundColor="white">

    <mx:Style>
        CustomLinkButton1 {
            skin: ClassReference("skins.CustomLinkButtonSkin1");
        }
    </mx:Style>

    <mx:ApplicationControlBar dock="true">
        <mx:Form styleName="plain">
            <mx:FormItem label="enabled:">
                <mx:CheckBox id="checkBox" selected="true" />
            </mx:FormItem>
        </mx:Form>
    </mx:ApplicationControlBar>

    <comps:CustomLinkButton1 id="linkButton"
            label="LinkButton"
            toggle="true"
            enabled="{checkBox.selected}"
            rollOverColor="red"
            selectionColor="haloOrange"
            toggleBackgroundColor="yellow" />

</mx:Application>

Or, you can set the skin style using ActionScript, as seen in the following example:

View MXML

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2008/09/08/extending-the-linkbutton-control-in-flex/ -->
<mx:Application name="LinkButton_skin_test"
        xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="vertical"
        verticalAlign="middle"
        backgroundColor="white"
        initialize="init();">

    <mx:Script>
        <![CDATA[
            import mx.binding.utils.BindingUtils;

            import comps.CustomLinkButton1;
            import skins.CustomLinkButtonSkin1;

            private var linkButton:CustomLinkButton1;

            private function init():void {
                linkButton = new CustomLinkButton1();
                linkButton.label = "LinkButton";
                linkButton.toggle = true;
                linkButton.setStyle("skin", CustomLinkButtonSkin1);
                linkButton.setStyle("rollOverColor", "red");
                linkButton.setStyle("selectionColor", "haloOrange");
                linkButton.setStyle("toggleBackgroundColor", "yellow");
                addChild(linkButton);

                BindingUtils.bindProperty(linkButton, "enabled",
                                            checkBox, "selected");
            }
        ]]>
    </mx:Script>

    <mx:ApplicationControlBar dock="true">
        <mx:Form styleName="plain">
            <mx:FormItem label="enabled:">
                <mx:CheckBox id="checkBox" selected="true" />
            </mx:FormItem>
        </mx:Form>
    </mx:ApplicationControlBar>

</mx:Application>

6 Responses to “Extending the LinkButton control in Flex”


  1. 1 Zavati Vladimir Sep 9th, 2008 at 1:26 pm

    Hello,

    Can you give an example about a secure authentification method for flex, I heard something about using Spring Acegi on Google, but didn’t seen a good example.

  2. 2 William McBee Sep 17th, 2008 at 2:59 pm

    I’m trying to follow this, however I’m having a slight problem trying to streamline this into one mxml where I have (in order):

    ButtonScrollingCanvas
    HBox
    Repeater
    LinkButton (label, toolTip, name and click(event) are all handled here)
    /Repeater
    /HBox
    /ButtonScrollingCanvas

    What I want to do is once a linkbutton is clicked, it should stay highlight until the next one is clicked. And this method, while darn close, isn’t working for me exactly.

  3. 3 Amy Oct 6th, 2008 at 6:35 pm

    Thanks, this makes sense, but I want to take it one step further and put the custom linkButton in a linkBar. Can you explain how to do that, or point me to something that does? I haven’t found anything. Thanks!

  4. 4 Ruslan Oct 15th, 2008 at 6:11 am

    Hi, good sample. It there way to hide rollover background at all?

    Thanks

  5. 5 peterd Oct 15th, 2008 at 7:18 am

    Ruslan,

    Yes. If you want to remove the rollover color you can either set the skin style to null, or extend the LinkButtonSkin class (mx.skins.halo.LinkButtonSkin.as) and set the alpha to 0% in each skin state.

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    
        <mx:Script>
            <![CDATA[
                import mx.controls.Alert;
    
                private function linkButton_click(evt:MouseEvent):void {
                    Alert.show(evt.currentTarget.label + " " + evt.type);
                }
            ]]>
        </mx:Script>
    
        <mx:LinkButton id="defaultLinkButton"
                label="Default LinkButton"
                click="linkButton_click(event);" />
    
        <mx:LinkButton id="customSkinLinkButton"
                label="Custom skin LinkButton"
                skin="TransparentLinkButtonSkin"
                click="linkButton_click(event);" />
    
        <mx:LinkButton id="nullSkinLinkButton"
                label="Null skin LinkButton"
                skin="{null}"
                click="linkButton_click(event);" />
    
    </mx:Application>
    

    And then my custom skin, TransparentLinkButtonSkin.as, looks like this:

    package {
        import mx.skins.halo.LinkButtonSkin;
    
        public class TransparentLinkButtonSkin extends LinkButtonSkin {
            public function TransparentLinkButtonSkin() {
                super();
            } // END function TransparentLinkButtonSkin();
    
            override protected function updateDisplayList(w:Number, h:Number):void {
                super.updateDisplayList(w, h);
    
                var cornerRadius:Number = getStyle("cornerRadius");
    
                graphics.clear();
    
                switch (name) {
                    case "upSkin":
                    case "overSkin":
                    case "downSkin":
                    case "disabledSkin":
                        // Draw invisible shape so we have a hit area.
                        drawRoundRect(
                            0, 0, w, h, cornerRadius,
                            0, 0);
                        break;
                } // END switch;
            } // END function updateDisplayList();
        } // END class TransparentLinkButtonSkin;
    } // END package;
    

    Peter

  6. 6 dandu Nov 17th, 2008 at 1:02 pm

    I recently had a customer who was trying to debug his Flex components. Under certain circumstances the updateDisplayList() method of his component was getting called and it wasn’t obvious why.

Leave a Reply

This blog is terrible at eating HTML tags. If you plan on posting code/XML, please escape your "<" characters as "&lt;" and your ">" characters as "&gt;".