12
Sep
07

Changing a slider control’s thumb skin

The following example shows how you can customize a slider control (HSlider or VSlider) and use your own custom embedded image instead of the default triangle thumb skin.

Full code after the jump.

View MXML

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2007/09/12/changing-a-slider-controls-thumb-skin/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="vertical"
        verticalAlign="middle"
        backgroundColor="white">

    <mx:Style>
        ToolTip {
            backgroundAlpha: 1.0;
            backgroundColor: haloBlue;
            fontWeight: bold;
            color: white;
        }

        HSlider {
            thumbSkin: Embed(source="assets/bug.png");
            dataTipPlacement: right;
            dataTipOffset: 0;
        }
    </mx:Style>

    <mx:HSlider id="slider"
            minimum="-10"
            maximum="20"
            labels="[-10, 0, 10, 20]"
            snapInterval="1"
            tickInterval="10"
            liveDragging="true"
            dataTipPrecision="0"
            showTrackHighlight="true" />

</mx:Application>

View source is enabled in the following example.

If you wanted to change the width and height of the thumb within the Slider, you can do this by extending the SliderThumb class and setting the width and height properties from within the constructor. For example, create a new file named “BigThumbClass.as” and save it in the same directory as your MXML file. Enter the following code into the BigThumbClass class:

package {
    import mx.controls.sliderClasses.SliderThumb;

    public class BigThumbClass extends SliderThumb {
        public function BigThumbClass() {
            super();
            this.width = 16;
            this.height = 16;
        }
    }
}

Now, in your MXML file, set the sliderThumbClass property to your custom BigThumbClass class, as seen in the following snippet:

<mx:HSlider id="slider"
        minimum="-10"
        maximum="20"
        labels="[-10, 0, 10, 20]"
        snapInterval="1"
        tickInterval="10"
        liveDragging="true"
        dataTipPrecision="0"
        showTrackHighlight="true"
        sliderThumbClass="BigThumbClass" />

View source is enabled in the following example.


17 Responses to “Changing a slider control's thumb skin”


  1. 1 Mike Sep 13th, 2007 at 1:07 pm

    Great article. Do you know of any way to apply different skins for sliders with multiple thumbs?

  2. 2 peterd Sep 13th, 2007 at 1:30 pm

    Mike,

    Try something like the following:

    <mx:Script>
        <![CDATA[
            import mx.controls.sliderClasses.SliderThumb;
    
            [Embed(source="assets/bullet_add.png")]
            private var BulletAdd:Class;
    
            [Embed(source="assets/bullet_delete.png")]
            private var BulletDelete:Class;
    
            private function initThumbs():void {
                var thumb1:SliderThumb = slider.getThumbAt(0);
                thumb1.setStyle("thumbSkin", BulletAdd);
    
                var thumb2:SliderThumb = slider.getThumbAt(1);
                thumb2.setStyle("thumbSkin", BulletDelete);
            }
        ]]>
    </mx:Script>
    
    <mx:HSlider id="slider"
            minimum="-10"
            maximum="20"
            labels="[-10, 0, 10, 20]"
            snapInterval="1"
            tickInterval="10"
            liveDragging="true"
            dataTipPrecision="0"
            showTrackHighlight="true"
            thumbCount="2"
            values="[2,8]"
            creationComplete="initThumbs()" />
    
  3. 3 Mike Sep 13th, 2007 at 2:41 pm

    Hi Peter,

    Brilliant. Thanks for the tip.

    Only one issue I had was with setting “thumbSkin”. Looks like the version of flex I’m using doesn’t support that. I have to explicitly set the thumbUpSkin, thumbDownSkin, etc. I’m using flex Builder Version: 2.0.155577.

    Regards,
    Mike

  4. 4 peterd Sep 13th, 2007 at 3:01 pm

    Yeah, sorry, I’m using Flex 3 beta so there may be some occasional differences like this. I usually don’t do a lot of backwards compatibility testing to make sure the examples work in earlier versions of the Flex SDK, so if you catch any other “gotchas” like that, note them in the comments. :)

    BFF,
    Peter

  5. 5 Mike Sep 13th, 2007 at 11:10 pm

    I’m trying to annotate video cue points using multiple thumbs on a slider. Works well but I’ve not figured out how to dynamically generate a new thumb and add it to the slider. Is there a simpler way or a better approach to doing something like this?

    Thanks,
    Mike

  6. 6 peterd Sep 13th, 2007 at 11:21 pm

    Mike,

    The above post only really addresses skinning an existing thumb skin, not adding new thumbs dynamically.

    Does that following snippet get you any closer?

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
            layout="vertical"
            verticalAlign="middle">
    
        <mx:Script>
            <![CDATA[
                private function addThumb():void {
                    slider.thumbCount = slider.thumbCount + 1;
                    var slVal:Array = slider.values;
                    slVal.push(slider.thumbCount);
                    slider.values = slVal;
                }
            ]]>
        </mx:Script>
    
        <mx:Button label="add thumb" click="addThumb()" />
    
        <mx:HSlider id="slider" allowThumbOverlap="true" />
    
    </mx:Application>
    

    Basically whenever you click the Button control, a new thumb is added (setting thumbCount \+=1). Then I assign the new slider thumb’s value by pushing a new value onto the “values” property. You’d want to clean that code up a bit. I just set the newest value to the thumb count, but its a bit clumsy.

    Hope that helps,
    Peter

  7. 7 Mike Sep 14th, 2007 at 8:31 am

    Hi Peter,

    Works like a champ. You have been a great help. I was stuck on adding the new thumb, thinking I needed to instantiate a new sliderThumb object and add it to the slider. Looks like this get done for you simply by updating the thumbCount.

    Thanks a million,
    Mike

  8. 8 Leon Sep 20th, 2007 at 10:18 pm

    Great article,

    I think i have found why flex builder 2 cannot display the custom skin correctly.

    It seems that we should define the following attributes in flex builder 2

    thumbUpSkin:Embed(source="assets/bug.png");
    thumbOverSkin:Embed(source="assets/bug.png");
    thumbDownSkin:Embed(source="assets/bug.png");
    
  9. 9 Ronzoni Nov 29th, 2007 at 8:42 pm

    I needed to change the thumbSkin with each thumb potentially different sizes.
    To prevent it from scaling I made this class:

    package player.gui.slider {
    	import mx.controls.sliderClasses.SliderThumb;
    
    	public class MySliderThumb extends SliderThumb {
    		public function MySliderThumb() {
    			super();
    		}
    
    		override protected function measure():void {
    			super.measure();
    			measuredHeight = minHeight;
    			measuredWidth = minWidth;
    		}
    	}
    }
    

    Not sure if that’s potentially problematic, or if there is any easier way to do that..

    Anyone know how I can make my thumb not overlap over the ends of the track (and still report the correct value)?

  10. 10 Ronzoni Nov 30th, 2007 at 2:12 pm

    I have two questions:

    1) How can I make my thumb not overlap the ends of the track?
    I haven’t even attempted this yet, too busy with other bugs, but it seems like it’s something that should be fairly desirable.

    2) I would like the measuredHeight of my slider to be only the track height. I can’t seem to access the track though in anyway..I’ve been trying very hard..

  11. 11 jack Dec 6th, 2007 at 6:33 am

    Hi,
    This is a big help. I tried it and have one serious problem. I’m emulating a scrollbar, but want the control of hslider. So the thumb is a rather large shape, 240 pixels. I’m using a skin for the track as well, and for some reason it’s leaving big gaps in the track when I use the thumbclass setting such a big width.

    Do you have any ideas?

    Thanks

  12. 12 john Dec 24th, 2007 at 9:07 am

    Hi,
    Thanks for your article.
    I have one question:
    like below:

    HSlider {
                thumbSkin: Embed(source="assets/bug.png");
                dataTipPlacement: right;
                dataTipOffset: 0;
            }
    

    I wan’t dynamic change the thumbSkin by coding.How can I code?

  13. 13 peterd Jan 8th, 2008 at 3:40 pm

    john,

    Something like the following should work:

    <?xml version="1.0" encoding="utf-8"?>
    <!-- main.mxml -->
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
            layout="vertical"
            verticalAlign="top"
            backgroundColor="white">
    
        <mx:Script>
            <![CDATA[
                [Bindable]
                [Embed(source="add.png")]
                private var icon1:Class;
    
                [Bindable]
                [Embed(source="delete.png")]
                private var icon2:Class;
    
                private function style1():void {
                    /* Short */
                    StyleManager.getStyleDeclaration("HSlider").setStyle("thumbSkin", icon1);
                }
    
                private function style2():void {
                    /* Long */
                    var cssObj:CSSStyleDeclaration = StyleManager.getStyleDeclaration("HSlider");
                    cssObj.setStyle("thumbSkin", icon2);
                }
            ]]>
        </mx:Script>
    
        <mx:Style>
            HSlider {
                thumbSkin: Embed(source="add.png");
                dataTipPlacement: right;
                dataTipOffset: 0;
            }
        </mx:Style>
    
        <mx:ApplicationControlBar dock="true">
            <mx:Button label="icon 1" icon="{icon1}" click="style1();" />
            <mx:Button label="icon 2" icon="{icon2}" click="style2();" />
        </mx:ApplicationControlBar>
    
        <mx:HSlider id="slider" sliderThumbClass="BulletThumbClass" />
    
    </mx:Application>
    
    /** BulletThumbClass.as */
    package {
        import mx.controls.sliderClasses.SliderThumb;
    
        public class BulletThumbClass extends SliderThumb {
            public function BulletThumbClass() {
                super();
            }
    
            override protected function measure():void {
                super.measure();
                measuredHeight = minHeight;
                measuredWidth = minWidth;
            }
        }
    }
    

    Hope that helps,
    Peter

    PS: Thanks to Ronzoni’s comments above for the measure() trick so you don’t have to hard-code icon dimensions.

  14. 14 jeffs Jan 22nd, 2008 at 12:02 pm

    Is it possible to use a UIComponent as a skin for say the thumbUpSkin. How would I go about assigning that to the hSlider?

  15. 15 Anand Jha Mar 8th, 2008 at 2:36 am

    Hi Peter

    Please help me in achieving the following:

    “To drag the region between the thumbs, if the HSlider has two thumbs”.

    Do we have any option in HSlider?

    Or

    Do i need to rewrite HSlider which will implement Slider?

    Thanx in advance

    ~Anand

  16. 16 peterd Mar 8th, 2008 at 10:18 am

    Anand,

    Something like Doug McCune’s Draggable Slider Component for Flex?

    Peter

  17. 17 JOse May 20th, 2008 at 1:19 pm

    Hi Peter,

    This is a big help. Thanks. You have been a great help. I´m from Uruguay and I needed use sliders from make a zoom in a column chart.

    Do you have any ideas?

    Thanks

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;".