如何在 iOS 13 中将 UISegmentedControl 的背景颜色设置为白色

How to set backgroundColor of UISegmentedControl to white in iOS 13

iOS 13 对 UISegmentedControl 进行了一些更改,包括切换选定段时非常漂亮的动画。但是我注意到它没有正确显示 backgroundColor 属性,它似乎总是带有一点色彩。

我已经看到回答如何设置 selectedSegmentTintColor 之类的问题,但我正在努力将 backgroundColor 设置为 .white,无论我做什么即使没有应用 tintColor 或类似设置,也总是显示出一点灰色。将 backgroundColor 设置为其他颜色会显示相同的行为,但最明显的是白色。更神秘的是,虽然这种差异出现在 iOS 13 模拟器和物理设备 运行 iOS 13 上,但可视化调试器(在 XCode 11 GM2 中)确实不显示这种差异!

这里有几个屏幕截图显示,即使 UISegmentedControlbackgroundColor 设置为与其后面显示的视图的 backgroundColor 相同,它们也略有不同。

设备运行iOS13(白色背景色)

与 Visual Debugger 中显示的相同 view/code(白色背景颜色)

设备运行iOS13(蓝色背景颜色)

我已经尝试了按照 SO post: 中的建议应用 backgroundImage 的建议,但最终将样式恢复为它在 [= 中的样子42=] 12 你也会失去漂亮的动画。

非常感谢任何指导或建议!我还向 Apple 提交了一份错误报告,看看是否有任何结果。

我也遇到了同样的问题,但没有很好的解决方法。所以我做了这个小的解决方法。我不喜欢它,我也不为此感到自豪,但它确实有效。

func fixBackgroundSegmentControl( _ segmentControl: UISegmentedControl){
    if #available(iOS 13.0, *) {
        //just to be sure it is full loaded
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { 
            for i in 0...(segmentControl.numberOfSegments-1)  {
                let backgroundSegmentView = segmentControl.subviews[i]
                //it is not enogh changing the background color. It has some kind of shadow layer 
                backgroundSegmentView.isHidden = true 
            }
        }
    }
}

SWIFT 3 & 4+

根据这个答案 ,如果您想要没有灰色覆盖的全白背景,只需将 tintColorbackgroundColor 替换为 UIColor.white

extension UISegmentedControl {
    func removeBorders() {
        setBackgroundImage(imageWithColor(color: backgroundColor!), for: .normal, barMetrics: .default)
        setBackgroundImage(imageWithColor(color: tintColor!), for: .selected, barMetrics: .default)
        setDividerImage(imageWithColor(color: UIColor.clear), 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!
    }
}

适合我(Swift 5)。

let background = myColors.background
let selectedColor = myColors.foreground

if #available(iOS 13.0, *)
{
    segmentedControl.tintColor = background
    segmentedControl.backgroundColor = background
    segmentedControl.selectedSegmentTintColor = selectedColor
    segmentedControl.setTitleTextAttributes([.foregroundColor: selectedColor as Any], for: .normal)
    segmentedControl.setTitleTextAttributes([.foregroundColor: background as Any], for: .selected)
}
else
{
    segmentedControl.tintColor = background
    segmentedControl.backgroundColor = selectedColor
    segmentedControl.layer.cornerRadius = 4
}

在 Xamarin.iOS 这对我有用:

class MySegmentedControl : UISegmentedControl
{
    int insertedIndex = 0;

    public override void InsertSubview(UIView view, nint atIndex)
    {
        base.InsertSubview(view, atIndex);

        if (insertedIndex == 2 || insertedIndex == 3)
            view.Hidden = true;

        insertedIndex++;
    }
}

我找到了最简单的解决方案。

let segmentControl: UISegmentControl = ... 
segmentControl.subviews.forEach { subview in
  subview.backgroundColor = .white
}

接受的答案可以简化,我们可以通过继承 UISegmentedControl 并覆盖 layoutSubviews 方法来避免使用 DispatchQueue.main.async 调用:

class SegmentedControl: UISegmentedControl {
  override func layoutSubviews() {
    super.layoutSubviews()
    for i in 0...(numberOfSegments - 1)  {
      subviews[i].isHidden = true
    }
  }
}