【问题标题】:How to set backgroundColor of UISegmentedControl to white in iOS 13如何在 iOS 13 中将 UISegmentedControl 的背景颜色设置为白色
【发布时间】:2020-01-26 02:10:00
【问题描述】:

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

我已经看到了回答如何设置selectedSegmentTintColor 等的问题,但我很难将backgroundColor 设置为.white,无论我做什么,它总是显示有点灰色即使没有应用 tintColor 或类似设置。将backgroundColor 设置为其他颜色显示相同的行为,但最明显的是白色。更令人费解的是,虽然这种差异在 iOS 13 模拟器和运行 iOS 13 的物理设备上都出现了,但可视化调试器(在 XCode 11 GM2 中)并没有显示出这种差异!

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

运行 iOS 13 的设备(白色背景颜色)

Visual Debugger 中显示的相同视图/代码(白色背景颜色)

运行 iOS 13 的设备(蓝色背景颜色)

我已尝试按照此 SO 帖子中的建议应用 backgroundImage 的建议:UISegmentedControl iOS 13 clear color 但最终将样式恢复到它在 iOS 12 中的外观,并且您也失去了漂亮的动画。

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

【问题讨论】:

  • 您解决了这个问题吗?我也一样
  • 不幸的是我没有。发布此问题几天后,我向 Apple 打开了一份错误报告,但遗憾的是到目前为止还没有得到任何回复。
  • 在下面查看我的答案,我通过这种方式解决了我的问题

标签: ios swift uisegmentedcontrol ios13


【解决方案1】:

我也有同样的问题,没有很酷的方法可以解决它。所以我做了这个小解决方法。我不喜欢它,我并不以此为荣,但它确实有效。

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 
            }
        }
    }
}

【讨论】:

  • 看看我下面的回答,我刚刚找到了一种比这更酷的方法,即使你的方式是有效的
  • 这成功了!我已经完全放弃了,感谢您分享您的解决方案。它有点骇人听闻,但考虑到手头情况的荒谬,它感觉很合适:)
  • 使用此代码,我的分段控件会丢失文本,但仍会显示灰色覆盖层。
  • 使用这个解决方案,段之间的分隔线在我的分段控件中消失了。你有同样的副作用吗?如果没有,你能分享一下你的分段控件的配置吗?
  • 这个解决方案对我不好,同时标题消失:/
【解决方案2】:

SWIFT 3 和 4+

从这个答案 https://stackoverflow.com/a/31652184/3249196 ,如果你想要一个没有灰色覆盖的全白背景,请将 tintColor 和 backgroundColor 替换为 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!
    }
}

【讨论】:

  • 嗨 Carioni,我之前实际上已经尝试过这种方法,除非我遗漏了一些东西,否则你会在更改选择时失去动画,这是我试图维护的。埃里克席尔瓦的建议虽然有点老套,但确实可以解决问题。
  • @Phil 你能分享一个视频示例吗?我不确定你指的是什么,因为我没有丢失任何动画
【解决方案3】:

为我工作 (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
}

【讨论】:

  • 这似乎适用于除 .white 和 .clear 之外的所有背景颜色。当您将其设置为这两种颜色中的任何一种时,显示的是丑陋的灰色。
  • @c0d3p03t 我认为灰色混合在任何浅色中都是可见的。我正在尝试使用浅棕褐色,但我也看到它带有 UIColor.yellow。
【解决方案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++;
    }
}

【讨论】:

    【解决方案5】:

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

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

    【讨论】:

    • 不幸的是,您使用此解决方案丢失了选定的背景颜色
    • 有什么建议如何处理?
    【解决方案6】:

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

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

    【讨论】:

      猜你喜欢
      • 2021-03-23
      • 2020-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-27
      • 2019-12-18
      • 1970-01-01
      相关资源
      最近更新 更多