UISegmentedControl iOS 13 清晰颜色

8
在 iOS 12 上,要获得一个带有清晰边框、清晰分隔线、所有元素都清晰的 UISegmentedControl 很容易。我所做的只是这样:
  settingControl.tintColor = .clear

   let font = myFont
   let boldfont = myBoldFont

  settingControl.setTitleTextAttributes([NSAttributedString.Key.foregroundColor : UIColor.white, NSAttributedString.Key.font:font], for: .normal)
  settingControl.setTitleTextAttributes([NSAttributedString.Key.foregroundColor : UIColor.red, NSAttributedString.Key.font:boldfont], for: .selected)

然后UISegmentedControl完全清除颜色(分隔线、背景、边框)

但在iOS 13中,我无法完全清除它。 我可以设置

settingControl.selectedSegmentTintColor = UIColor.clear

但是它仍然不能清除背景颜色和分隔线。
我尝试将背景颜色设置为透明,但没有效果。
 settingControl.backgroundColor = UIColor.clear

我也尝试设置了清晰的图像,但仍然没有任何效果:
 public extension UIImage {

  /**
   Returns image with size 1x1px of certain color.
   */
 class func imageWithColor(color : UIColor) -> UIImage? {
    let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
    UIGraphicsBeginImageContext(rect.size)
    let context = UIGraphicsGetCurrentContext()

    context?.setFillColor(color.cgColor)

    context?.fill(rect)

    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return image
}

 }

然后是这个:

  let clearImage = UIImage.imageWithColor(color: UIColor.clear)
    settingControl.setDividerImage(clearImage, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)


   settingControl.setBackgroundImage(clearImage, for: .normal, barMetrics: .default)
   settingControl.setBackgroundImage(clearImage, for: .selected, barMetrics: .default)

这是在iOS 12上的外观。在iOS 13上,似乎不可能实现。

This is how it looks like on iOS 12. On iOS 13, this seems impossible.

2个回答

13

这里有一个方法可以在 iOS 13 中复制那个简单的分段控件:

import UIKit
import PlaygroundSupport

class PlainSegmentedControl: UISegmentedControl {
    override init(items: [Any]?) {
        super.init(items: items)

        setup()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    // Used for the unselected labels
    override var tintColor: UIColor! {
        didSet {
            setTitleTextAttributes([.foregroundColor: tintColor!, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .normal)
        }
    }

    // Used for the selected label
    override var selectedSegmentTintColor: UIColor? {
        didSet {
            setTitleTextAttributes([.foregroundColor: selectedSegmentTintColor ?? tintColor!, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .selected)
        }
    }

    private func setup() {
        backgroundColor = .clear

        // Use a clear image for the background and the dividers
        let tintColorImage = UIImage(color: .clear, size: CGSize(width: 1, height: 32))
        setBackgroundImage(tintColorImage, for: .normal, barMetrics: .default)
        setDividerImage(tintColorImage, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)

        // Set some default label colors
        setTitleTextAttributes([.foregroundColor: UIColor.black, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .normal)
        setTitleTextAttributes([.foregroundColor: tintColor!, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13, weight: .regular)], for: .selected)
    }
}

以下是一些可以放在playground里的测试代码:

// Create a dark green view as a test background
let bg = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 100))
bg.backgroundColor = UIColor(red: 0.224, green: 0.408, blue: 0.467, alpha: 1)

// The plain segmented control
let seg = PlainSegmentedControl(items: ["Number One", "Number Two", "Number Three"])
seg.tintColor = .white
seg.selectedSegmentTintColor = .green
seg.selectedSegmentIndex = 0
bg.addSubview(seg)
PlaygroundPage.current.liveView = bg

这是用于创建指定大小的颜色图片的UIImage扩展:

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()!)!
    }
}

1
为什么UIImage的大小是32?这是一个适用于所有分段控制器的固定大小吗? - Deepak Sharma
它会生成一个与常规分段控件相同高度的分段控件。 - rmaddy
我尝试了一个大小为1x1的resizedImageWithCapInsets,但奇怪的是,它似乎限制了文本的大小为1x1像素。现在唯一的问题是这个硬编码的大小是否会继续工作。 - Deepak Sharma
你可以使用1x1像素的图片,但是你需要设置分段控件的高度,例如 seg.frame.size.height = 32 - rmaddy
如何在使用故事板时与分段控件一起工作? - GarySabo

1

如果要使您的UISegmentedControl背景透明,您可以尝试以下方法:

segmentedControl.backgroundColor = .clear
segmentedControl.setBackgroundImage(UIImage(), for: .normal, barMetrics: .default)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接