¿Cómo cambiar los colores de un segmento en un UISegmentedControl en iOS 13?

109

A UISegmentedControltiene una nueva apariencia en iOS 13 y el código existente para alterar los colores del control segmentado ya no funciona como lo hacía.

Antes de iOS 13, podía configurar tintColory que se usaría para el borde alrededor del control segmentado, las líneas entre los segmentos y el color de fondo del segmento seleccionado. Luego, podría cambiar el color de los títulos de cada segmento usando el atributo de color de primer plano con titleTextAttributes.

Bajo iOS 13, tintColorno hace nada. Puede configurar los controles segmentados backgroundColorpara cambiar el color general del control segmentado. Pero no puedo encontrar ninguna forma de alterar el color utilizado como fondo del segmento seleccionado. La configuración de los atributos del texto aún funciona. Incluso intenté establecer el color de fondo del título, pero eso solo afecta al fondo del título, no al resto del color de fondo del segmento seleccionado.

En resumen, ¿cómo se modifica el color de fondo del segmento actualmente seleccionado de a UISegmentedControlen iOS 13? ¿Existe una solución adecuada, utilizando API públicas, que no requiera profundizar en la estructura de subvista privada?

No hay nuevas propiedades en iOS 13 para UISegmentedControlo UIControly ninguno de los cambios UIViewson relevantes.

rmaddy
fuente

Respuestas:

134

A partir de IOS 13B3, ahora hay un selectedSegmentTintColorsobre UISegmentedControl.

Para cambiar el color general del control segmentado, use su backgroundColor.

Para cambiar el color del segmento seleccionado utilice selectedSegmentTintColor.

Para cambiar el color / fuente de los títulos de los segmentos no seleccionados, use setTitleTextAttributescon un estado de .normal/ UIControlStateNormal.

Para cambiar el color / fuente de los títulos de segmento seleccionados, use setTitleTextAttributescon un estado de .selected/ UIControlStateSelected.

Si crea un control segmentado con imágenes, si las imágenes se crean como imágenes de plantilla, los controles segmentados tintColorse utilizarán para colorear las imágenes. Pero esto tiene un problema. Si establece el tintColormismo color que selectedSegmentTintColor, la imagen no será visible en el segmento seleccionado. Si establece el tintColormismo color que backgroundColor, las imágenes de los segmentos no seleccionados no serán visibles. Esto significa que su control segmentado con imágenes debe usar 3 colores diferentes para que todo sea visible. O puede usar imágenes que no sean de plantilla y no establecer el tintColor.

En iOS 12 o anterior, simplemente configure los controles segmentados tintColoro confíe en el color de tinte general de la aplicación.

rmaddy
fuente
¿Cómo configuramos el controlador de segmento sin bordes? No veo ninguna configuración para esto en iOS 13. Anteriormente, configurar tintcolor era suficiente para obtener un control de segmento sin bordes.
Deepak Sharma
Agregue Color de borde, etc. para que todos puedan encontrar todos los problemas relacionados con el color del segmento que se resuelven aquí. que dices ? :)
Yogesh Patel
1
@YogeshPatel ¿Qué pasa con el color del borde? No hay color de borde en iOS 13 y en iOS 12 está configurado con lo tintColorque ya está cubierto en la respuesta.
rmaddy
@rmaddy He configurado este [segmentedControl.layer setBorderColor: [[UIColor whiteColor] CGColor]]; [segmentedControl.layer setBorderWidth: 0.5]; me da borde y color de borde en iOS 13.
Yogesh Patel
1
Oh, esa frontera. Eso se aplica a cualquier vista, no solo a un control segmentado. Eso está más allá del alcance de la pregunta original y esta respuesta. Tu comentario es suficiente.
rmaddy
47

A partir de Xcode 11 beta 3

Ahora está la selectedSegmentTintColorpropiedad UISegmentedControl.

Ver la respuesta de rmaddy


Para recuperar la apariencia de iOS 12

No pude teñir el color del segmento seleccionado, espero que se solucione en una próxima versión beta.

Configurar la imagen de fondo del estado seleccionado no funciona sin configurar la imagen de fondo del estado normal (que elimina todo el estilo de iOS 13)

Pero pude devolverlo a la apariencia de iOS 12 (o lo suficientemente cerca, no pude devolver el radio de la esquina a su tamaño más pequeño).

No es ideal, pero un control segmentado de color blanco brillante parece un poco fuera de lugar en nuestra aplicación.

(No sabía que UIImage(color:)era un método de extensión en nuestro código base. Pero el código para implementarlo está en la web)

extension UISegmentedControl {
    /// Tint color doesn't have any effect on iOS 13.
    func ensureiOS12Style() {
        if #available(iOS 13, *) {
            let tintColorImage = UIImage(color: tintColor)
            // Must set the background image for normal to something (even clear) else the rest won't work
            setBackgroundImage(UIImage(color: backgroundColor ?? .clear), for: .normal, barMetrics: .default)
            setBackgroundImage(tintColorImage, for: .selected, barMetrics: .default)
            setBackgroundImage(UIImage(color: tintColor.withAlphaComponent(0.2)), for: .highlighted, barMetrics: .default)
            setBackgroundImage(tintColorImage, for: [.highlighted, .selected], barMetrics: .default)
            setTitleTextAttributes([.foregroundColor: tintColor, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .normal)
            setDividerImage(tintColorImage, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
            layer.borderWidth = 1
            layer.borderColor = tintColor.cgColor
        }
    }
}

Imagen que muestra el efecto del código anterior

Jonathan.
fuente
Esta podría ser una buena solución. Todavía no he tenido la oportunidad de probar esto, pero ¿esto también requiere una llamada setTitleTextAttributespara que el título del segmento seleccionado tenga un color blanco?
rmaddy
Hmm, parece que debería, pero aparentemente no. No tengo acceso a ese cajero automático de uso de código, pero la imagen de la izquierda se crea con ese código.
Jonathan.
8
stackoverflow.com/a/33675160/5790492 para la extensión UIImage (color :).
Nik Kov
1
Sería bueno si agregara la extensión UIImage, de esta manera, su respuesta no está completa iho
FredFlinstone
1
@VityaShurapov lo configura para cuando está resaltado y seleccionado, no es una matriz de estados pasados, sino un conjunto de opciones, lo que significa que los valores se combinan para crear un nuevo estado.
Jonathan.
36

IOS 13 y Swift 5.0 (Xcode 11.0) Control de segmento 100% funcionando

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

 if #available(iOS 13.0, *) {
      yoursegmentedControl.backgroundColor = UIColor.black
      yoursegmentedControl.layer.borderColor = UIColor.white.cgColor
      yoursegmentedControl.selectedSegmentTintColor = UIColor.white
      yoursegmentedControl.layer.borderWidth = 1

      let titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]    
      yoursegmentedControl.setTitleTextAttributes(titleTextAttributes, for:.normal)

      let titleTextAttributes1 = [NSAttributedString.Key.foregroundColor: UIColor.black]
      yoursegmentedControl.setTitleTextAttributes(titleTextAttributes1, for:.selected)
  } else {
              // Fallback on earlier versions
}
Maulik Patel
fuente
7
¿Intentaste configurar el fondo como blanco? para mí se está volviendo grisáceo
Ronit
@ItanHant ¿Qué xcode y lenguaje rápido estás usando?
Maulik Patel
@Ronit por supuesto !! Lo intentaré, pero por favor, dígame qué tipo de pantalla de salida ahora
Maulik Patel
swift 5, xcode 11.3! ¡muestra lo que quiere! no el que quiero :)
Itan Hant
15

Probé la solución alternativa y me funciona muy bien. Aquí está la versión Objective-C:

@interface UISegmentedControl (Common)
- (void)ensureiOS12Style;
@end
@implementation UISegmentedControl (Common)
- (void)ensureiOS12Style {
    // UISegmentedControl has changed in iOS 13 and setting the tint
    // color now has no effect.
    if (@available(iOS 13, *)) {
        UIColor *tintColor = [self tintColor];
        UIImage *tintColorImage = [self imageWithColor:tintColor];
        // Must set the background image for normal to something (even clear) else the rest won't work
        [self setBackgroundImage:[self imageWithColor:self.backgroundColor ? self.backgroundColor : [UIColor clearColor]] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
        [self setBackgroundImage:tintColorImage forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
        [self setBackgroundImage:[self imageWithColor:[tintColor colorWithAlphaComponent:0.2]] forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
        [self setBackgroundImage:tintColorImage forState:UIControlStateSelected|UIControlStateSelected barMetrics:UIBarMetricsDefault];
        [self setTitleTextAttributes:@{NSForegroundColorAttributeName: tintColor, NSFontAttributeName: [UIFont systemFontOfSize:13]} forState:UIControlStateNormal];
        [self setDividerImage:tintColorImage forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
        self.layer.borderWidth = 1;
        self.layer.borderColor = [tintColor 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;
}
@end
Colin Blake
fuente
2
No estoy seguro de que funcione con CGRectMake(0.0f, 0.0f, 1.0f, 1.0f): de mis pruebas con Xcode 11 beta, recttenía que ser del mismo tamaño que los límites del control segmentado.
Cœur
2
Desde iOS13 beta 6, el tintcolor no aparecía en un botón seleccionado, así que tuve que agregar una línea: [self setTitleTextAttributes: @ {NSForegroundColorAttributeName: UIColor.blackColor, NSFontAttributeName: [UIFont systemFontOfSize: 13]} forState: UIControlStateSetateName:
Peter Johnson
Cuando intento usar esto [[UISegmentedControl appearance] ensureiOS12Style], obtengo una excepción. ¿Alguna idea de lo que está pasando? Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSMethodSignature getArgumentTypeAtIndex:]: index (2) out of bounds [0, 1]'
Jeremy Hicks
13

A partir de Xcode 11 beta 3

Ahora está la selectedSegmentTintColorpropiedad UISegmentedControl.

¡Gracias @rmaddy!


Respuesta original, para Xcode 11 beta y beta 2

¿Existe una solución adecuada, utilizando API públicas, que no requiera profundizar en la estructura de subvista privada?

Con Xcode 11.0 beta, parece ser un desafío hacerlo según las reglas, porque básicamente requiere volver a dibujar todas las imágenes de fondo para cada estado usted mismo, con esquinas redondeadas, transparencia y resizableImage(withCapInsets:). Por ejemplo, necesitaría generar una imagen coloreada similar a:
ingrese la descripción de la imagen aquí

Entonces, por ahora, la forma de profundizar en las subvistas parece mucho más fácil:

class TintedSegmentedControl: UISegmentedControl {

    override func layoutSubviews() {
        super.layoutSubviews()

        if #available(iOS 13.0, *) {
            for subview in subviews {
                if let selectedImageView = subview.subviews.last(where: { $0 is UIImageView }) as? UIImageView,
                    let image = selectedImageView.image {
                    selectedImageView.image = image.withRenderingMode(.alwaysTemplate)
                    break
                }
            }
        }
    }
}

Esta solución aplicará correctamente el color del tinte a la selección, como en: ingrese la descripción de la imagen aquí

Cœur
fuente
1
Otorgado porque se acaba el tiempo, pero preferiblemente se encontrará una solución que no implique excavar en jerarquías privadas :)
Jonathan.
@Jonathan. Gracias. Ya tiene la solución más cercana que no involucra mirar la jerarquía: porque una vez que lo setBackgroundImagehace .normal, debe configurar todas las demás imágenes (incluidos otros estados y setDividerImage), probablemente con algunas UIBezierPathy resizableImage(withCapInsets:), lo que lo hace demasiado complejo si queremos el diseño de iOS 13 de esta manera.
Cœur
Sí, idealmente se solucionará en una versión beta
Jonathan.
3
Esto ya no es necesario a partir de iOS 13b3. Ahora está la selectedSegmentTintColorpropiedad UISegmentedControl.
rmaddy
11

La versión rápida de @Ilahi Charfeddine responde:

if #available(iOS 13.0, *) {
   segmentedControl.setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
   segmentedControl.selectedSegmentTintColor = UIColor.blue
} else {
   segmentedControl.tintColor = UIColor.blue
}
Vignan S
fuente
10
if (@available(iOS 13.0, *)) {

    [self.segmentedControl setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor whiteColor], NSFontAttributeName: [UIFont systemFontOfSize:13]} forState:UIControlStateSelected];
    [self.segmentedControl setSelectedSegmentTintColor:[UIColor blueColor]];

} else {

[self.segmentedControl setTintColor:[UIColor blueColor]];}
Ilahi Charfeddine
fuente
7

iOS13 UISegmentController

cómo utilizar:

segment.setOldLayout(tintColor: .green)

extension UISegmentedControl
{
    func setOldLayout(tintColor: UIColor)
    {
        if #available(iOS 13, *)
        {
            let bg = UIImage(color: .clear, size: CGSize(width: 1, height: 32))
             let devider = UIImage(color: tintColor, size: CGSize(width: 1, height: 32))

             //set background images
             self.setBackgroundImage(bg, for: .normal, barMetrics: .default)
             self.setBackgroundImage(devider, for: .selected, barMetrics: .default)

             //set divider color
             self.setDividerImage(devider, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)

             //set border
             self.layer.borderWidth = 1
             self.layer.borderColor = tintColor.cgColor

             //set label color
             self.setTitleTextAttributes([.foregroundColor: tintColor], for: .normal)
             self.setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
        }
        else
        {
            self.tintColor = tintColor
        }
    }
}
extension UIImage {
    convenience init(color: UIColor, size: CGSize) {
        UIGraphicsBeginImageContextWithOptions(size, false, 1)
        color.set()
        let ctx = UIGraphicsGetCurrentContext()!
        ctx.fill(CGRect(origin: .zero, size: size))
        let image = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()

        self.init(data: image.pngData()!)!
    }
}
Jigar Darji
fuente
1
Este es el único enfoque que funcionó para mí: las imágenes de fondo. selectedSegmentTintColor no funcionó por alguna razón.
DenNukem
7

XCODE 11.1 y iOS 13

Basado en la respuesta de @Jigar Darji pero una implementación más segura.

Primero creamos un inicializador de conveniencia que falla:

extension UIImage {

convenience init?(color: UIColor, size: CGSize) {
    UIGraphicsBeginImageContextWithOptions(size, false, 1)
    color.set()
    guard let ctx = UIGraphicsGetCurrentContext() else { return nil }
    ctx.fill(CGRect(origin: .zero, size: size))
    guard
        let image = UIGraphicsGetImageFromCurrentImageContext(),
        let imagePNGData = image.pngData()
        else { return nil }
    UIGraphicsEndImageContext()

    self.init(data: imagePNGData)
   }
}

Luego extendemos UISegmentedControl:

extension UISegmentedControl {

func fallBackToPreIOS13Layout(using tintColor: UIColor) {
    if #available(iOS 13, *) {
        let backGroundImage = UIImage(color: .clear, size: CGSize(width: 1, height: 32))
        let dividerImage = UIImage(color: tintColor, size: CGSize(width: 1, height: 32))

        setBackgroundImage(backGroundImage, for: .normal, barMetrics: .default)
        setBackgroundImage(dividerImage, for: .selected, barMetrics: .default)

        setDividerImage(dividerImage,
                        forLeftSegmentState: .normal,
                        rightSegmentState: .normal, barMetrics: .default)

        layer.borderWidth = 1
        layer.borderColor = tintColor.cgColor

        setTitleTextAttributes([.foregroundColor: tintColor], for: .normal)
        setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
    } else {
        self.tintColor = tintColor
    }
  }
}
FredFlinstone
fuente
¡Perfecto! ¡Gracias!
Senocico Stelian
5

Aquí está mi opinión sobre la respuesta de Jonathan. Para Xamarin.iOS (C #), pero con correcciones para el tamaño de la imagen. Al igual que con el comentario de Cœur sobre la respuesta de Colin Blake, hice todas las imágenes excepto el divisor del tamaño del control segmentado. El divisor es 1 x altura del segmento.

public static UIImage ImageWithColor(UIColor color, CGSize size)
{
    var rect = new CGRect(0, 0, size.Width, size.Height);
    UIGraphics.BeginImageContext(rect.Size);
    var context = UIGraphics.GetCurrentContext();
    context.SetFillColor(color.CGColor);
    context.FillRect(rect);
    var image = UIGraphics.GetImageFromCurrentImageContext();
    UIGraphics.EndImageContext();
    return image;
}

// https://stackoverflow.com/a/56465501/420175
public static void ColorSegmentiOS13(UISegmentedControl uis, UIColor tintColor, UIColor textSelectedColor, UIColor textDeselectedColor)
{
    if (!UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
    {
        return;
    }

    UIImage image(UIColor color)
    {
        return ImageWithColor(color, uis.Frame.Size);
    }

    UIImage imageDivider(UIColor color)
    {
        return ImageWithColor(color, 1, uis.Frame.Height);
    }

    // Must set the background image for normal to something (even clear) else the rest won't work
    //setBackgroundImage(UIImage(color: backgroundColor ?? .clear), for: .normal, barMetrics: .default)
    uis.SetBackgroundImage(image(UIColor.Clear), UIControlState.Normal, UIBarMetrics.Default);

    // setBackgroundImage(tintColorImage, for: .selected, barMetrics: .default)
    uis.SetBackgroundImage(image(tintColor), UIControlState.Selected, UIBarMetrics.Default);

    // setBackgroundImage(UIImage(color: tintColor.withAlphaComponent(0.2)), for: .highlighted, barMetrics: .default)
    uis.SetBackgroundImage(image(tintColor.ColorWithAlpha(0.2f)), UIControlState.Highlighted, UIBarMetrics.Default);

    // setBackgroundImage(tintColorImage, for: [.highlighted, .selected], barMetrics: .default)
    uis.SetBackgroundImage(image(tintColor), UIControlState.Highlighted | UIControlState.Selected, UIBarMetrics.Default);

    // setTitleTextAttributes([.foregroundColor: tintColor, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .normal)
    // Change: support distinct color for selected/de-selected; keep original font
    uis.SetTitleTextAttributes(new UITextAttributes() { TextColor = textDeselectedColor }, UIControlState.Normal); //Font = UIFont.SystemFontOfSize(13, UIFontWeight.Regular)
    uis.SetTitleTextAttributes(new UITextAttributes() { TextColor = textSelectedColor, }, UIControlState.Selected); //Font = UIFont.SystemFontOfSize(13, UIFontWeight.Regular)

    // setDividerImage(tintColorImage, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
    uis.SetDividerImage(imageDivider(tintColor), UIControlState.Normal, UIControlState.Normal, UIBarMetrics.Default);

    //layer.borderWidth = 1
    uis.Layer.BorderWidth = 1;

    //layer.borderColor = tintColor.cgColor
    uis.Layer.BorderColor = tintColor.CGColor;
}
t9mike
fuente
3

Puede implementar el siguiente método

extension UISegmentedControl{
    func selectedSegmentTintColor(_ color: UIColor) {
        self.setTitleTextAttributes([.foregroundColor: color], for: .selected)
    }
    func unselectedSegmentTintColor(_ color: UIColor) {
        self.setTitleTextAttributes([.foregroundColor: color], for: .normal)
    }
}

Código de uso

segmentControl.unselectedSegmentTintColor(.white)
segmentControl.selectedSegmentTintColor(.black)
Zain Anjum
fuente
0

Si bien las respuestas anteriores son excelentes, la mayoría de ellas obtienen mal el color del texto dentro del segmento seleccionado. He creado UISegmentedControlsubclase que se puede utilizar en IOS 13 y 13 pre-IOS dispositivos y usar la propiedad tintColor como lo haría en pre IOS 13 dispositivos.

    class LegacySegmentedControl: UISegmentedControl {
        private func stylize() {
            if #available(iOS 13.0, *) {
                selectedSegmentTintColor = tintColor
                let tintColorImage = UIImage(color: tintColor)
                setBackgroundImage(UIImage(color: backgroundColor ?? .clear), for: .normal, barMetrics: .default)
                setBackgroundImage(tintColorImage, for: .selected, barMetrics: .default)
                setBackgroundImage(UIImage(color: tintColor.withAlphaComponent(0.2)), for: .highlighted, barMetrics: .default)
                setBackgroundImage(tintColorImage, for: [.highlighted, .selected], barMetrics: .default)
                setTitleTextAttributes([.foregroundColor: tintColor!, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .normal)

                setDividerImage(tintColorImage, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
                layer.borderWidth = 1
                layer.borderColor = tintColor.cgColor

// Detect underlying backgroundColor so the text color will be properly matched

                if let background = backgroundColor {
                    self.setTitleTextAttributes([.foregroundColor: background, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .selected)
                } else {
                    func detectBackgroundColor(of view: UIView?) -> UIColor? {
                        guard let view = view else {
                            return nil
                        }
                        if let color = view.backgroundColor, color != .clear {
                            return color
                        }
                        return detectBackgroundColor(of: view.superview)
                    }
                    let textColor = detectBackgroundColor(of: self) ?? .black

                    self.setTitleTextAttributes([.foregroundColor: textColor, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .selected)
                }
            }
        }

        override func tintColorDidChange() {
            super.tintColorDidChange()
            stylize()
        }
    }

    fileprivate extension UIImage {
        public convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {
          let rect = CGRect(origin: .zero, size: size)
          UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
          color.setFill()
          UIRectFill(rect)
          let image = UIGraphicsGetImageFromCurrentImageContext()
          UIGraphicsEndImageContext()

          guard let cgImage = image?.cgImage else { return nil }
          self.init(cgImage: cgImage)
        }
    }

Al usar el tintColorDidChangemétodo, nos aseguramos de que stylizese llamará al método cada vez que la tintColorpropiedad cambie en la vista de segmento, o en cualquiera de las vistas subyacentes, que es el comportamiento preferido en iOS.

Resultado: ingrese la descripción de la imagen aquí

Adán
fuente
-2

Ampliando un poco la respuesta de Jonathan en caso de que no quieras redondear las esquinas

extension UISegmentedControl {
    /// Tint color doesn't have any effect on iOS 13.
    func ensureiOS12Style(roundCorner: Bool = true) {
        if #available(iOS 13, *) {
            let tintColorImage = UIImage(color: tintColor)
            // Must set the background image for normal to something (even clear) else the rest won't work
            setBackgroundImage(UIImage(color: backgroundColor ?? .clear), for: .normal, barMetrics: .default)
            setBackgroundImage(tintColorImage, for: .selected, barMetrics: .default)
            setBackgroundImage(UIImage(color: tintColor.withAlphaComponent(0.2)), for: .highlighted, barMetrics: .default)
            setBackgroundImage(tintColorImage, for: [.highlighted, .selected], barMetrics: .default)
            setTitleTextAttributes([.foregroundColor: tintColor, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .normal)
            setDividerImage(tintColorImage, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)

            if !roundCorner {
                layer.masksToBounds = false

                let borderView = UIView()
                borderView.layer.borderWidth = 1
                borderView.layer.borderColor = UIColor.black.cgColor
                borderView.isUserInteractionEnabled = false
                borderView.translatesAutoresizingMaskIntoConstraints = false

                addSubview(borderView)

                NSLayoutConstraint(item: borderView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1, constant: 0).isActive = true
                NSLayoutConstraint(item: borderView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0).isActive = true
                NSLayoutConstraint(item: borderView, attribute: .width, relatedBy: .equal, toItem: self, attribute: .width, multiplier: 1, constant: 0).isActive = true
                NSLayoutConstraint(item: borderView, attribute: .height, relatedBy: .equal, toItem: self, attribute: .height, multiplier: 1, constant: 0).isActive = true
            }
        }
    }
}
GoNinja
fuente