UISlider setMaximumTrackTintColor

11,679

Solution 1

That is strange, both min and max work fine for me and I can even have it animate color change. All I can suggest is re-create the slider and also @synthesize.

@synthesize slider;

- (void)viewDidLoad
{
[super viewDidLoad];
[slider setMinimumTrackTintColor:[UIColor orangeColor]];
[slider setMaximumTrackTintColor:[UIColor blueColor]];



// Do any additional setup after loading the view, typically from a nib.
}

Slider with 2 different colors

Solution 2

Avoid setting the maximumTrackTintColor redundantly. When my code was updating the color twice, the maximum line would just disappear. I was able to reproduce it with a simple UISlider, like this:

    UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(0, 0, 150, 23)];
    slider.maximumTrackTintColor = [UIColor whiteColor];
    slider.maximumTrackTintColor = [UIColor whiteColor];

Instead of a white track, this slider will have no maximum track when displayed on the screen under iOS 8.

Solution 3

This is an Apple bug, and it still exists in iOS 8. I've seen it when trying to modify the maximum tint color of sliders via an proxy setter on a subclass. Changing the minimum tint color works fine and shows no errors, but trying to change the maximum tint color throws tons of bad context errors and often draws that portion of the slider gradient in the wrong location (which proves it does indeed not have a good context).

I could find no workaround for the problem, but will file a bug report.

Solution 4

For me the problem occurred because I had subclassed UISlider to create a custom trackRectForBounds that was returning a CGRect with an invalid size. My original implementation (and maybe some iOS version's implementations?) returned a track bounds with a zero or negative size depending on the UISlider's bounds. It appears that it is related to the fact that setting minimum/maximumTrackTintColor will call trackRectForBounds, possibly in order to create a track image.

The fix to the problem is making sure that the track bounds will be valid when setting minimum/maximum track tint colors.

Option 1: use initWithFrame that is sufficiently sized for the UISlider

UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(0,0,100,38)];
slider.minimumTrackTintColor = [UIColor greenColor];
slider.maximumTrackTintColor = [UIColor orangeColor];
// ... rest of view setup ...

Option 2: add the slider and force auto-layout so that it is correctly sized before setting the tint colors

UISlider *slider = [[UISlider alloc] init]; // <-- problem, zero size
[view addSubview:slider];
// ... other view setup, including constraints ...
[view layoutIfNeeded]; // forced layout to give slider a non-zero size
slider.minimumTrackTintColor = [UIColor greenColor];
slider.maximumTrackTintColor = [UIColor orangeColor];

Option 3: fix the override to make sure that it will return a rectangle of non-zero size, regardless of bounds.

- (CGRect)trackRectForBounds:(CGRect)bounds {
     // example, inset left/right by 2 (thus width - 4)
     // track height is 5 pixels, centered in bounds.
     return CGRectMake(
         CGRectGetMinX(bounds) + 2,
         CGRectGetMinY(bounds) + (CGRectGetHeight(bounds) + 5)/2.0,
         MAX(10, CGRectGetWidth(bounds) - 4), // use max make sure positive.
         5)
}

Note: I am creating UISliders after the viewDidLoad so Ahufford's answer wouldn't work for me, but I presume this could also explain it. I would also guess Ahufford's answer will probably work best in most cases.

Share:
11,679

Related videos on Youtube

Reid
Author by

Reid

Updated on September 26, 2022

Comments

  • Reid
    Reid over 1 year

    I'm trying to dynamically configure the track color on a UISlider.

    This line of code works perfectly for setting the low side of the slider track.

    [self.sliderBar setMinimumTrackTintColor:[UIColor redColor]];

    When trying to do the same thing for the high side of the slider track, this line of code reports 3 fatal errors to the debug log.

    [self.sliderBar setMaximumTrackTintColor:[UIColor redColor]];

    <Error>: CGContextAddPath: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context  and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.
    
    <Error>: clip: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context  and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.
    
    <Error>: CGContextDrawLinearGradient: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context  and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.
    

    I have also tried to set the track tint colors using dot notation, but the same 3 errors were reported.

    self.sliderBar.maximumTrackTintColor = [UIColor redColor];

    I am very confused why the minimum track tint color is properly set, while the maximum track tint color is breaking. Any assistance would be greatly appreciated.

    This issue seems to be related to this question, but I'm not 100% sure since I'm not working with graphics (only setting the tint color).

  • Vlad
    Vlad almost 9 years
    Also this is reproduced when you set maximumTrackTintColor in storyboard and in code together.
  • Christian Schnorr
    Christian Schnorr almost 9 years
    @VincentDucastel Dot notation actually calls the very same setter behind the scenes. The two snippets are equivalent except for the colors you are passing in.
  • Christian Schnorr
    Christian Schnorr almost 9 years
    Dot notation actually calls the very same setter behind the scenes. The two snippets are equivalent except for the colors you are passing in.
  • Vincent Ducastel
    Vincent Ducastel almost 9 years
    Sorry, I had to be wrong during my tests ... But I can not change maximumTrackTintColor via Interface Builder.... I edit my answer. Thanks.
  • Vincent Ducastel
    Vincent Ducastel almost 9 years
    Sorry, I had to be wrong during my tests ... But I can not change maximumTrackTintColor via Interface Builder.... I edit my answer. Thanks.
  • mrketchup
    mrketchup almost 9 years
    The workaround I've gone with is to create an brand new UISlider with all the same properties, throw away the original, and drop the new one in right where the original was.
  • Gary Z
    Gary Z about 8 years
    I don't know about other iOS versions but in 8.4.1, examining the maximumTrackTintColor's value and assigning it to the desired color only if it's not already that color isn't working. I have to set maximumTrackTintColor to a color that I don't want and then set it to the color that I do want. With an inequality "if" statement, the maximum line disappears.
  • Doug Gerecht
    Doug Gerecht over 7 years
    I had a similar issue with a subclassed UISlider. It has a custom background that was loaded in the initWith* methods. However, trackRectForBounds was getting called during the super initialization and it referenced the background that wasn't yet loaded. You saved me tons of time tracking this down! Thank you!