iOS13 上的 UIControlSegment 背景颜色不再透明

UIControlSegment background color is not transparent anymore on iOS13

我有一个 UISegmentedControl。 它在 iOS13 之前工作正常(我将 backgroundColor 和 tintColor 都设置为清除)。 但是现在,我没有得到相同的结果。 我的 SegmentedControl 有一个浅灰色层。 我做了一些研究,但没有任何效果。 (我遇到了同样的问题:https://forums.developer.apple.com/thread/123955

之前的状态:

当前状态 - iOS13:

为了满足设计要求,我也遇到了这个问题。在我的例子中,SegmentedControl 背景颜色应该是白色或透明颜色,因为视图的背景颜色也是白色。

所以我只是在 SegmentControl 背景中添加了一个白色的 UImage,这个技巧对我有用。

if (@available(iOS 13.0, *)) {
   [segmentController setBackgroundImage:[UIImage imageNamed:@"someWhiteImage"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
}

虽然这不是一个完美的解决方案,但使用这个技巧可以满足我的要求。您现在也可以在背景中添加纯色背景图像。希望有人告诉我们正确的处理方式。

需要设计及之前 iOS 13

iOS13

之后

所以添加白色背景图片对我有用

.selectedSegmentTintColor 定义所选按钮的颜色和 .layer.backgroundColor 整个 UISegmentedControl 背景的颜色。

事实证明,这不适用于背景清晰或白色,因为在 iOS 13 中,在分段控件的背景和分隔符上添加了一种背景图像。

解决方法是使用 UIGraphicsGetImageFromCurrentImageContext 从颜色创建图像。试试这个:

class ViewController: UIViewController {

    @IBOutlet weak var segmentedControl: UISegmentedControl!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        segmentedControl.setiOS12Layout(tintColor: .red)
    }
}

extension UISegmentedControl {

    func setiOS12Layout(tintColor: UIColor) {

        if #available(iOS 13, *) {

            let background = UIImage(color: .clear, size: CGSize(width: 1, height: 32))
             let divider = UIImage(color: tintColor, size: CGSize(width: 1, height: 32))
             self.setBackgroundImage(background, for: .normal, barMetrics: .default)
             self.setBackgroundImage(divider, for: .selected, barMetrics: .default)
             self.setDividerImage(divider, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
             self.layer.borderWidth = 1
             self.layer.borderColor = tintColor.cgColor
             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 context = UIGraphicsGetCurrentContext()!
        context.fill(CGRect(origin: .zero, size: size))
        let image = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        self.init(data: image.pngData()!)!
    }
}

结果:

您可以创建一个扩展来使您的段控制清晰

segmentControl.clearBG()

这是扩展

extension UISegmentedControl {
    func clearBG() {
        setBackgroundImage(imageWithColor(color: UIColor.white), for: .normal, barMetrics: .default)
        setBackgroundImage(imageWithColor(color: UIColor.white), for: .normal, barMetrics: .default)
        setDividerImage(imageWithColor(color: .white), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
    }

    // create a 1x1 image with this color
    private func imageWithColor(color: UIColor) -> UIImage {
        let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
        UIGraphicsBeginImageContext(rect.size)
        let context = UIGraphicsGetCurrentContext()
        context!.setFillColor(color.cgColor);
        context!.fill(rect);
        let image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return image!
    }
}

感谢@Maulik Pandya 的回答, 我已经稍微改进了你的答案。

extension UISegmentedControl {
  func clearBG() {
    let clearImage = UIImage().imageWithColor(color: .clear)
    setBackgroundImage(clearImage, for: .normal, barMetrics: .default)
    setBackgroundImage(clearImage, for: .selected, barMetrics: .default)
    setDividerImage(clearImage, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
  }
}

public extension UIImage {
  public func imageWithColor(color: UIColor) -> UIImage {
    let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
    UIGraphicsBeginImageContext(rect.size)
    guard let context = UIGraphicsGetCurrentContext() else { return UIImage()}
    context.setFillColor(color.cgColor)
    context.fill(rect)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image!
  }
}