How to change the colors of a segment in a UISegmentedControl in iOS 13?

前端 未结 14 739
醉话见心
醉话见心 2020-11-30 18:13

A UISegmentedControl has a new appearance in iOS 13 and existing code to alter the colors of the segmented control no longer work as they did.

Prior to

相关标签:
14条回答
  • 2020-11-30 18:42

    Expanding a little bit on Jonathan answer in case you don't want round corners

    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
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-30 18:43

    As of iOS 13b3, there is now a selectedSegmentTintColor on UISegmentedControl.

    To change the overall color of the segmented control use its backgroundColor.

    To change the color of the selected segment use selectedSegmentTintColor.

    To change the color/font of the unselected segment titles, use setTitleTextAttributes with a state of .normal/UIControlStateNormal.

    To change the color/font of the selected segment titles, use setTitleTextAttributes with a state of .selected/UIControlStateSelected.

    If you create a segmented control with images, if the images are created as template images, then the segmented control's tintColor will be used to color the images. But this has a problem. If you set the tintColor to the same color as selectedSegmentTintColor then the image won't be visible in the selected segment. If you set the tintColor to the same color as backgroundColor, then the images on the unselected segments won't be visible. This means your segmented control with images must use 3 different colors for everything to be visible. Or you can use non-template images and not set the tintColor.

    Under iOS 12 or earlier, simply set the segmented control's tintColor or rely on the app's overall tint color.

    0 讨论(0)
提交回复
热议问题