8

I'm trying to position an additional UIView centered above the thumb in a UISlider. To do this, I need the width of the thumb image. In iOS6, this works fine. I can use:

CGFloat thumbWidth = self.navSlider.currentThumbImage.size.width;

(As seen in this answer: How to get the center of the thumb image of UISlider)

This returns 0.0f in iOS7. I've also tried reading it using:

UIImage *thumb = [self.navSlider thumbImageForState:UIControlStateNormal];

But thumb ends up nil.

Is it possible to read the size of the default slider thumb image? Or will I have to find it, set a constant, and how Apple doesn't change it later?

Community
  • 1
  • 1
Pj Dietz
  • 921
  • 9
  • 16

5 Answers5

8

The docs on the currentThumbImage property say:

If no custom thumb images have been set using the setThumbImage:forState: method, this property contains the value nil. In that situation, the receiver uses the default thumb image for drawing.

The docs on thumbImageForState: are less clear:

Return Value The thumb image associated with the specified state, or nil if an appropriate image could not be retrieved.

I think you might be out of luck trying to figure out the default thumb size. How about installing a "custom" thumb image that looks exactly like the system image? That would solve the problem of Apple changing it out from under you.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • 2
    I was hoping to do this without custom images, but I'm thinking this may be the only way. At least it will look consistent across OSs. Thanks! – Pj Dietz Jan 23 '14 at 18:53
8

I use this in my subclass:

CGRect trackRect = [self trackRectForBounds:self.bounds];
CGRect thumbRect = [self thumbRectForBounds:self.bounds trackRect:trackRect value:0];
CGSize thumbSize = thumbRect.size;
Rudolf Adamkovič
  • 31,030
  • 13
  • 103
  • 118
  • 1
    Smart answer. However, we can still get the size or the rect of the thumb without subclass: ` var trackRect = slider.trackRectForBounds(slider.bounds) var thumbRect = slider.thumbRectForBounds(slider.bounds, trackRect: trackRect, value: slider.value) ` Using `slider?.superview.convertRect(thumbRect, fromView: slider)` to use it in the superview's coordinate. – bubuxu Oct 11 '14 at 04:57
  • It is so great! – Valeriy Van Feb 27 '17 at 10:29
  • Surprised this isn't the accepted answer. – Albert Renshaw Dec 28 '22 at 00:07
0

You need to set the initial thumb image using setThumbImage forState. This works fine for me in iOS7 and returns the correct width of the image. The slider is setup in a storyboard and connected via an IBOutlet.

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self.slider setThumbImage:[UIImage imageNamed:@"tick.jpg"] forState:UIControlStateNormal];

    float check = self.slider.currentThumbImage.size.width;
    NSLog(@"Check is %f", check);

}
GuybrushThreepwood
  • 5,598
  • 9
  • 55
  • 113
  • I was hoping to do this without providing custom images for the slider. That may be the only way to get this to work though. – Pj Dietz Jan 23 '14 at 17:04
0

I believe this will sometimes return 0, if the layout flow hasn't completed. I had some trouble with it.

CGRect thumbRect = [self thumbRectForBounds:self.bounds
                                  trackRect:[self trackRectForBounds:self.bounds]
                                      value:self.value];
CGFloat thumbDiameter = CGRectGetHeight(thumbRect);
TheJeff
  • 3,665
  • 34
  • 52
0

Here is another one that works, however it is a little "hackier" than the first one, and makes an assumption on the default thumb Image width won't change in future versions of iOS (past 11)

- (CGFloat)thumbImageWidth // default thumb image is 30 px,
{
    double imgThumbImageWidth = self.currentThumbImage.size.width;
    if (imgThumbImageWidth && imgThumbImageWidth != 0 && imgThumbImageWidth != thumbImageWidth) {
        thumbImageWidth = imgThumbImageWidth;
    }
    else if (!thumbImageWidth || thumbImageWidth == 0) { // No custom image set, use 30
        thumbImageWidth = 31;
    }
    return thumbImageWidth;
}
TheJeff
  • 3,665
  • 34
  • 52