Search code examples
iosobjective-cuisegmentedcontrol

Segmented Controller background grey after iOS13


I'm currently having problems with an iOS 13 segmented controller. I have this method in which I change the appearance of my segmented controller, it worked great until iOS 13 got out. now I the segmentedController has a grey background always, even if I set the background color to white, or black or whatever.

What Can I do?

- (void)modifySegmentedControl{
    if (@available(iOS 13.0, *)) {
        [_segmentedControl setBackgroundColor:UIColor.clearColor];
        [_segmentedControl setSelectedSegmentTintColor:UIColor.clearColor];
    } else {
         //I had this for <iOS13, it works great
        [_segmentedControl setBackgroundColor:UIColor.clearColor];
        [_segmentedControl setTintColor:UIColor.clearColor];
    }

    [_segmentedControl setTitleTextAttributes:
       [NSDictionary dictionaryWithObjectsAndKeys:
        [UIColor colorWithRed:0.25 green:0.25 blue:0.25 alpha:0.6], NSForegroundColorAttributeName,
        [UIFont fontWithName:@"Poppins-Medium" size:15.0], NSFontAttributeName,
       nil]
    forState: UIControlStateNormal];

    [_segmentedControl setTitleTextAttributes:
       [NSDictionary dictionaryWithObjectsAndKeys:
        [UIColor colorWithRed:0.25 green:0.25 blue:0.25 alpha:1.0], NSForegroundColorAttributeName,
        [UIFont fontWithName:@"Poppins-Medium" size:15.0], NSFontAttributeName,
       nil]
    forState: UIControlStateSelected];

    self->greenBar = [[UIView alloc] init];
//This needs to be false since we are using auto layout constraints
    [self->greenBar setTranslatesAutoresizingMaskIntoConstraints:NO];
    [self->greenBar setBackgroundColor:[UIColor colorWithRed:0.00 green:0.58 blue:0.27 alpha:1.0]]; //Kelley green
//
    [_vistaTable addSubview:self->greenBar];
//
    [self->greenBar.topAnchor constraintEqualToAnchor:_segmentedControl.bottomAnchor].active = YES;
    [self->greenBar.heightAnchor constraintEqualToConstant:3].active = YES;
    [self->greenBar.leftAnchor constraintEqualToAnchor:_segmentedControl.leftAnchor].active = YES;
    [self->greenBar.widthAnchor constraintEqualToAnchor:_segmentedControl.widthAnchor multiplier:0.5].active = YES;
}

Solution

  • Try this:

    if (@available(iOS 13.0, *)) {
        self.segmentedControl.selectedSegmentTintColor = UIColor.redColor;
        self.segmentedControl.layer.backgroundColor = UIColor.greenColor.CGColor;
    }
    

    .selectedSegmentTintColor defines the selected button color and .layer.backgroundColor the color for the whole UISegmentedControl background.

    This is the result:

    enter image description here

    EDIT

    It turns out this won't work for background clear or white, since on iOS 13 a sort of background image is added on the background and dividers of the segmented control:

    enter image description here

    A workaroud is create an image from color with UIGraphicsGetImageFromCurrentImageContext . The code looks like this:

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        if (@available(iOS 13.0, *)) {
            self.segmentedControl.selectedSegmentTintColor = UIColor.redColor;
            self.segmentedControl.layer.backgroundColor = UIColor.clearColor.CGColor;
            [self customizeSegmentedControlWithColor: UIColor.whiteColor];
        }
    }
    
    - (void)customizeSegmentedControlWithColor:(UIColor *)color {
    
        UIImage *tintColorImage = [self imageWithColor: color];
        [self.segmentedControl setBackgroundImage:[self imageWithColor:self.segmentedControl.backgroundColor ? self.segmentedControl.backgroundColor : [UIColor clearColor]] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
        [self.segmentedControl setBackgroundImage:tintColorImage forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
        [self.segmentedControl setBackgroundImage:[self imageWithColor:[color colorWithAlphaComponent:0.2]] forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
        [self.segmentedControl setBackgroundImage:tintColorImage forState:UIControlStateSelected|UIControlStateSelected barMetrics:UIBarMetricsDefault];
        [self.segmentedControl setDividerImage:tintColorImage forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
        self.segmentedControl.layer.borderWidth = 1;
        self.segmentedControl.layer.borderColor = [color CGColor];
    }
    
    - (UIImage *)imageWithColor: (UIColor *)color {
        CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
        UIGraphicsBeginImageContext(rect.size);
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetFillColorWithColor(context, [color CGColor]);
        CGContextFillRect(context, rect);
        UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return theImage;
    }
    

    Check more about it here.

    This is the result for background view with color and segmented control white:

    enter image description here

    And is the result for background view white and segmented control with color:

    enter image description here