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.

52 thoughts on “Changing a slider control’s thumb skin

  1. 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()" />
    
  2. 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

  3. 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

  4. 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

  5. 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

  6. 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

  7. 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");
    
  8. 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)?

  9. 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..

  10. 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

  11. 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?

  12. 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.

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

  14. 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

  15. 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

  16. Hi, gr8 discussion.

    I am having problem in highlighting a track.
    when we set showTrackHighlight="true" then only the track portion on left of thumb is painted.
    how can I highlight right portion of a track i.e. rest of the track.

    I want to paint track portion in two colors.

    Do any one have any ideas?

    Thanks.

  17. i couldn’t change my thumb. when i used the code above, i was getting this error message “cannot resolve attribute thumbskin for component type mx.controls.HSlider”. I’m using Adobe flex 2. I will appreciate your quick response.

  18. Why can’t you specify the thumbSkin image source in the constructor of the BigThumbClass? Wouldn’t that make more sense?

  19. Actually I couldn’t manage to make it work with the sliderThumbClass="BigThumbClass" with the given error of something like “the definition of BigThumbClass cannot be found”, until I put brackets around it: sliderThumbClass="{BigThumbClass}".

    greetings

  20. When using multiple thumbs, only the first two thumbs are highlighted(color filled with first two thumbs). Is it possible to fill color for other pair of thumbs.

    your help is highly important.

    thanks
    Guru

  21. Hi Friends!
    first of all I would like to say thanks for this post.

    Please help me out, I just want to change the bars below slider.
    I have designed gradients in my UI but I am unable to customize the bars below slider.

    avn

  22. Hi Peter

    Thanks for the great tutorials… I have been looking all over for this but cannot find it – is there a way to set the slider thickness? I know we can set it for the tick but for the slider itself??

    Thanks

    – Sami

  23. Hi Peter

    Thanks for that – I tried setting a jpg skin for the “trackSkin” property and it worked… though it’s a bit tricky

    BR
    – Sami

  24. Hello Peter,

    I have to show tooltip for the hslider on rollover of the slider icon..

    Can u please help me with that .Is there any such method.

    Regards
    Anurag

  25. Hi,

    I have created hslider with some reference site. I need to fire the event of thumbSkin change movement to function sliderChange. I have got value doesn’t macth for requirement. And also didn’t get the proper Currrent Slider value for checking for my requirement. Please any body help with this point.

           private function sliderChange(event:SliderEvent):void {
                  Alert.show("Slider Value"+(Slider(event.currentTarget)));           
                  var currentSlider:Slider=Slider(event.currentTarget);
                  txt.text="{Math.round(currentSlider.value)}";
                  var val:Number = Math.round(currentSlider.value);
     
                   if(val &lt; 50)
                    {
                     theme.visible = true; 
                     themes.visible = false;
                    }
                    else
                    {
                      themes.visible = true;
                        theme.visible = false; 
                    }
          }

    Regards
    yuva

  26. Hi all,

    is it possible to create a non-stretchy thumbIcon on a slider or scrollbar? I’m trying to create a custom scrollbar. I’m only using a simple trackSkin with a small, circular (15px by 15px) thumbIcon. I’ve tried a lot of things to get this working, but nothing seems to be working. At this moment I’ve a .png with transparency to the background, and de scaleGridTop and bottom set to the last pixel of the image. This keeps the thumbIcon intact, but it creates a big kind of ‘margin’ (in fact its a largely stretched 1px transparent part of the png). Is there some sort of option that says ‘unscaledThumbIcon = true’ or anything like it… (Sorry, I’m a noob)

    Greetz and thanx in advance!

  27. This was a great help!

    Do you know of a way to assign colors to each thumb from the flex colorpicker? Since there are a LOT of colors to choose from, I can’t just swap out icons for the thumb.

    1. @ATD,

      You can change thumb colors by using the getThumbAt() method:

      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
                      horizontalAlign="left">
       
          <mx:Script>
              <![CDATA[
                  protected function sl_creationCompleteHandler():void {
                      sl.getThumbAt(0).setStyle("fillColors", ["red", "red"]);
                      sl.getThumbAt(0).setStyle("themeColor", "red");
                      sl.getThumbAt(1).setStyle("fillColors", ["haloGreen", "haloGreen"]);
                      sl.getThumbAt(1).setStyle("themeColor", "haloGreen");
                  }
              ]]>
          </mx:Script>
       
          <mx:ApplicationControlBar dock="true">
              <mx:Label id="sdkVer" initialize="sdkVer.text = mx_internal::VERSION;" />
          </mx:ApplicationControlBar>
       
          <mx:HSlider id="sl"
                      thumbCount="2"
                      allowThumbOverlap="true"
                      creationComplete="sl_creationCompleteHandler();" />
       
      </mx:Application>

      Peter

  28. Hi Peter and the FE community. First I want to thank you for this wonderfull site. You’re helping a lot of people man. I hope we could give back someday.

    Here’s my question.
    When I set two differents skins for a thumb (for instance one for the upSkin and one for the overSkin), it seems that only the upSkin has the custom size. When I point the thumb with the mouse it goes back to the default size. Do you think we need to override another method to get this problem solved ?

    My code is the same than yours except in the css where I have a skin for each thumb state.

  29. Hi, this article is great! But i can’t still figure out one thing. I would like to position some of the thumbs a bit lower than others (below tracker line). Is this possible? Or should I emulate this by creating “special” images?

    1. @np,

      I believe you can tweak the thumbOffset style. I thought I had an example of this on my blog, but I cannot find it so I’ll try and post a simple example shortly.

      <mx:HSlider id="sl" thumbOffset="{sl.value}" liveDragging="true" />

      Peter

      1. Tkank you very much. Works like a charm :) But what if I need to position one (or few – but not all) of the thumbs a little bit higher than the others? I tried to change thubm y property but it doesn’t help.

      2. @np,

        This works for me in Flex 3.5 SDK. I had to use the updateComplete because when I tried setting the y property in the creationComplete event handler, the thumb offset would snap back to it’s original value after dragging the thumb:

        <?xml version="1.0" encoding="utf-8"?>
        <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
                layout="vertical"
                verticalAlign="middle"
                backgroundColor="white">
         
            <mx:Script>
                <![CDATA[
                    protected function setThumbY(evt:Event):void {
                        sl.getThumbAt(1).y = 10;
                    }
                ]]>
            </mx:Script>
         
            <mx:HSlider id="sl"
                    thumbCount="2"
                    values="[3,7]"
                    showTrackHighlight="true"
                    updateComplete="setThumbY(event);"/>
         
        </mx:Application>

        Peter

  30. Hi all,
    I am really new to flex and I am trying to make a slider with animated thumb(i.e. I want to reload the thumb in few milliseconds so that it would look like animation). I used the example above to put a picture on the thumb but when I try to change it with setStyle method it’s not changing…If anyone can help…here’s my code:

    ….

    ….
    public function MoveSheep():void
    {
    import mx.controls.sliderClasses.SliderThumb;
    slidersheep.setStyle(“thumbSkin”, “{sec.source}”);
    //Alert.show(“sheep”, slidersheep.getStyle(“thumbSkin.source”));
    }

    Alert is indicating the new source but visually, there is no change.
    And one more question…if I try to declare picture “sec” in AS I constantly get the error “1114 public attribute can used in this package”.
    I know that these are very stupid questions but I can’t fix them :)
    tsveti

  31. &ltmx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”absolute” xmlns:player=”org.bytearray.gif.player.*”&gt
    &ltmx:HSlider id=”slidersheep”
    change=”MoveSheep()”
    snapInterval=”0.5″
    tickInterval=”10″
    liveDragging=”true”
    showTrackHighlight=”true”
    sliderThumbClass=”BigThumbClass” width=”732″ height=”117″
    thumbSkin=”@Embed(source=’first.png’)” y=”10″ /&gt

    &ltmx:Image id=”sec” source=”second.png” x=”10″ y=”189″/&gt

  32. Thank you for another great article!

    One side note — it would be more logical to put “sliderThumbClass” property into the CSS as well.

  33. Great article, thank you very much! By the way, you may do the same by overriding measure() method like this:

    package components.parts
    {
    import mx.controls.sliderClasses.SliderThumb;
    import mx.core.mx_internal;

    use namespace mx_internal;

    public class BigSliderThumb extends SliderThumb {

    override protected function measure():void {
    super.measure();
    measuredWidth = currentSkin.measuredWidth;
    measuredHeight = currentSkin.measuredHeight;
    }
    }
    }

  34. simple in flex 4 :

    mx|Slider{

    accent-color:#cccccc;
    show-track-highlight:true;
    tick-color:#6f7777;
    data-tip-offset:50;
    thumb-skin:Embed(source=”../images/flex_arrow.png”);

    }
    but how to change the background skin(image) for the background strip (horizontal line behind the thumb)

Comments are closed.