Change iPhone UISlider bar image
Asked Answered
S

7

31

I'm using a UISlider in my app but I'd like to use a custom "look-and-feel" for it. I have changed the thumb to my own image but is there a way to change the bar also? I have a bar image I would like to use but can't see how to do this.

I have found how to change the max and min image but not the bar itself.

Spirochaetosis answered 4/3, 2010 at 12:48 Comment(2)
I have tried the [slider setMinimumTrackImage:forState:] method but this uses the image and scales it according to where the slider is placed. What I would like is to use a single image across the whole slider that remains static while the thumb is moved across it. Imagine a volume slider with a wedge to represent the relative volumes empty at one end and full at the other. When the slider is moved the wedge remains as it is. This is what I'd like to be able to do. Thanks!Spirochaetosis
Can you share samples of the custom slider pictures with the users?Insecure
T
60

You were right to use -setMinimumTrackImage:forState: and -setMaximumTrackImage:forState: methods. What you missed is that you should provide stretchable UIImage to them, the rest is taken care of automagically:

UIImage *sliderLeftTrackImage = [[UIImage imageNamed: @"SliderMin.png"] stretchableImageWithLeftCapWidth: 9 topCapHeight: 0];
UIImage *sliderRightTrackImage = [[UIImage imageNamed: @"SliderMax.png"] stretchableImageWithLeftCapWidth: 9 topCapHeight: 0];
[mySlider setMinimumTrackImage: sliderLeftTrackImage forState: UIControlStateNormal];
[mySlider setMaximumTrackImage: sliderRightTrackImage forState: UIControlStateNormal];

You can use the same image for both the min and max parts.

Torr answered 4/3, 2010 at 13:20 Comment(2)
actually, you answer can merge with Steve Melvin's one to make a complete solution.Bob
FYI on iOS 5 depending on your slider image, you will get some screwed up tilingVaporetto
P
25

The simplest solution would be to render a UIImage behind the control to represent the track. The thumbknob can be changed with:

[mySlider setThumbImage:[UIImage imageNamed:@"thumb_image.png"] forState:UIControlStateNormal];

A side-effect of this is that the track isn't rendered unless you provide your own. This, combined with the UIImage, provide you with a custom UISlider without you having to subclass anything.

Progress answered 11/3, 2010 at 21:22 Comment(2)
Doesn't appear to be true anymore for standard UISliders in iOS 5, unless I've missed something.Rennie
[[UISlider appearanceWhenContainedIn:[self class], nil] setThumbImage:[UIImage...] forState:UIControlStateNormal];. I think you can also do UIControlStateHighlighted to do a "touch down" image.Rheinland
H
8

Putting it all together in a modern way

If you define the UISlider in a Storyboard the best place to style the Slider is in the View's subclass. In awakeFromNib you can change the button, left and right track.

This call is deprecated in iOS 5 stretchableImageWithLeftCapWidth:topCapHeight:

- (void)awakeFromNib
{
    [super awakeFromNib];

    UIImage *thumbImage = [UIImage imageNamed:@"slider-button"];
    [self.slider setThumbImage:thumbImage forState:UIControlStateNormal];

    UIImage *sliderLeftTrackImage = [UIImage imageNamed: @"slider-fill"];
    sliderLeftTrackImage = [sliderLeftTrackImage resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeStretch];
    UIImage *sliderRightTrackImage = [UIImage imageNamed: @"slider-track"];
    sliderRightTrackImage = [sliderRightTrackImage resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeStretch];
    [self.slider setMinimumTrackImage:sliderLeftTrackImage forState:UIControlStateNormal];
    [self.slider setMaximumTrackImage:sliderRightTrackImage forState:UIControlStateNormal];
}
Hagio answered 27/7, 2013 at 8:42 Comment(0)
A
8

enter image description here

Here is a way to add a track image that is not stretched so you can have e.g. a wedge shape in the background just as the OP asked:

Swift 3.0:

let trackImg = image.resizableImage(withCapInsets: .zero, resizingMode: .tile)
slider.setMinimumTrackImage(trackImg, for: .normal)
slider.setMaximumTrackImage(trackImg, for: .normal)

Important: make sure that the width of your slider is exactly the same as the width of the image!

Archway answered 14/12, 2016 at 17:14 Comment(0)
G
4

stretchableImageWithLeftCapWidth: has been deprecated since iOS 5.0. The docs say to use 'capInsets' property instead. Here's an easy way to do that:

Create three images, the min (left) track, the max (right) track, and the thumb. For this example, assume the min and max track images are 34p H x 18p W, something like this: min track and this: enter image description here.

Create the images as usual:

UIImage *thumbImage = [UIImage imageNamed:@"sliderThumb.png"];

UIImage *sliderMinTrackImage = [UIImage imageNamed: @"sliderMin.png"];

UIImage *sliderMaxTrackImage = [UIImage imageNamed: @"sliderMax.png"];

For my 18 point wide image examples, the inner point on the left and the right can be stretched to fit the track, but the ends should have unstretchable cap sizes 17 points wide (hence the capInsets):

sliderMinTrackImage = [sliderMinTrackImage resizableImageWithCapInsets:UIEdgeInsetsMake(0, 17, 0, 0)];

sliderMaxTrackImage = [sliderMaxTrackImage resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 17)];

Then set the images on your UISlider as always:

[slider setThumbImage:thumbImage forState:UIControlStateNormal];
[slider setMinimumTrackImage:sliderMinTrackImage forState:UIControlStateNormal];
[slider setMaximumTrackImage:sliderMaxTrackImage forState:UIControlStateNormal];
Geotropism answered 26/11, 2013 at 22:14 Comment(0)
K
1

You need to subclass UISlider and override:

- (CGRect)trackRectForBounds:(CGRect)bounds

Discussion You should not call this method directly. If you want to customize the track rectangle, you can override this method and return a different rectangle. The returned rectangle is used to scale the track and thumb images during drawing.

Kooima answered 4/3, 2010 at 13:7 Comment(0)
I
0

I am doing this but the back bar is not showing perfectly in iOS 5.1 but in iOS 6.0 its displaying

here is my code

 UIImage *stetchLeftTrack = [[UIImage imageNamed:@"spectrum_horizontal_bar.png"]
                                stretchableImageWithLeftCapWidth:15.0 topCapHeight:0.0];
 UIImage *stetchRightTrack = [[UIImage imageNamed:@"spectrum_horizontal_bar.png"]
                                 stretchableImageWithLeftCapWidth:15.0 topCapHeight:0.0];
 [self.slider_Sprectrum setMinimumTrackImage:stetchLeftTrack forState:UIControlStateNormal];
 [self.slider_Sprectrum setMaximumTrackImage:stetchRightTrack forState:UIControlStateNormal];
Iterate answered 24/12, 2012 at 8:10 Comment(4)
@Hari Karam Singh [[UISlider appearanceWhenContainedIn:[self class], nil] setMinimumTrackImage:stetchLeftTrack forState:UIControlStateNormal]; [[UISlider appearanceWhenContainedIn:[self class], nil] setMaximumTrackImage:stetchRightTrack forState:UIControlStateNormal];Iterate
Hi Dk Kumar i am too facing same prob in IOS 5 but working in IOS 6.I am using two images for min and Max where both are same.Thumb image is a small transparent glow image.In IOS i could see a line behind the thumb...Can u plz help how you have solved in your case to avoid skewing/stretching...Lugansk
try removing stretchableImageWithLeftCapWidth ... use only [UIImage imageNamed:@"spectrum_horizontal_bar.png"] ... It will start showing the correct colors while sliding the slider. Only one problem I noticed here that it changes the left corner radius of slider when you move to max and min value... I'm looking to its solutions too.Pinchhit
moreover, stretchableImageWithLeftCapWidth has deprecated in iOS 5. use resizableImageWithCapInsets as alternate.Pinchhit

© 2022 - 2024 — McMap. All rights reserved.