如何从分段控件中删除边框

How to remove border from segmented control

如何删除分段控件的外边框? 我已将分隔线图像设置为我想要的,但现在要跟随我的应用程序的模拟,我需要有一个没有外边框的分段控件。

您必须了解的是 backgroundColor 属性 不是有状态的。 因此你必须使用 setBackgroundImage(_:for:barMetrics:)

我们可以使用以下函数轻松删除边框和分隔线。

对于 Swift 3 & 4+:

extension UISegmentedControl {
    func removeBorders() {
        setBackgroundImage(imageWithColor(color: backgroundColor ?? .clear), 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 2.2:

extension UISegmentedControl {
    func removeBorders() {
        setBackgroundImage(imageWithColor(backgroundColor!), forState: .Normal, barMetrics: .Default)
        setBackgroundImage(imageWithColor(tintColor!), forState: .Selected, barMetrics: .Default)
        setDividerImage(imageWithColor(UIColor.clearColor()), forLeftSegmentState: .Normal, rightSegmentState: .Normal, barMetrics: .Default)
    }

    // create a 1x1 image with this color
    private func imageWithColor(color: UIColor) -> UIImage {
        let rect = CGRectMake(0.0, 0.0, 1.0, 1.0)
        UIGraphicsBeginImageContext(rect.size)
        let context = UIGraphicsGetCurrentContext()
        CGContextSetFillColorWithColor(context, color.CGColor);
        CGContextFillRect(context, rect);
        let image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return image
    }
}

调用上面的函数。

segmentedControl.removeBorders()

参考:Remove UISegmentedControl separators completely. (iphone)

感谢 https://whosebug.com/users/3921490/amagain 提供 Swift 3 版本。

这是 Sohil 答案的 swift 3 版本,可能会对其他人有所帮助。它确实帮助了我。 :)

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

如果要保存单元格之间的边框

extension UISegmentedControl {
  func removeBorders() {
    if let backgroundColor = backgroundColor, let backgroundImage = UIImage.imageWithSize(size: CGSize.one_one, color: backgroundColor){
      setBackgroundImage(backgroundImage, for: .normal, barMetrics: .default)
    }

    if let tintColor = tintColor, let tintImage = UIImage.imageWithSize(size: CGSize.one_one, color: tintColor){
      setBackgroundImage(tintImage, for: .selected, barMetrics: .default)
        setDividerImage(tintImage, forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
    }
  }
}

extension CGSize{
  static var one_one: CGSize{
    return CGSize(width: 1.0, height: 1.0)
  }
}

extension UIImage{
  static func imageWithSize(size : CGSize, color : UIColor = UIColor.white) -> UIImage? {
    var image:UIImage? = nil
    UIGraphicsBeginImageContext(size)
    if let context = UIGraphicsGetCurrentContext() {
      context.setFillColor(color.cgColor)
      context.addRect(CGRect(origin: CGPoint.zero, size: size));
      context.drawPath(using: .fill)
      image = UIGraphicsGetImageFromCurrentImageContext();
    }
    UIGraphicsEndImageContext()
    return image
  }
}

希望对大家有所帮助

Swift - 4

将 Segment 控件的 Background 颜色和 Tint 颜色设置为相同的颜色。 然后 "set titleTextAttributes" 你的 Segment control

    segmentedControl.tintColor = UIColor.red
    segmentedControl.backgroundColor = UIColor.red
    let attributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
    segmentedControl.setTitleTextAttributes(attributes, for: .normal)
    segmentedControl.setTitleTextAttributes(attributes, for: .selected)

您可能有不想要圆角边框的用例,因为如果它嵌入在单元格中,您不想看到它。在这种情况下,将自动布局约束设置为 -2 并且边框将被隐藏,因为它会超出单元格边框。

如果您只需要文本段控制,请使用,

segmentControl.backgroundColor = .clear
segmentControl.tintColor = .clear

let attributes: [NSAttributedString.Key : Any] = [.font : UIFont(family: .medium, ofSize: 13)!, .foregroundColor : UIColor.white]
segmentControl.setTitleTextAttributes(attributes, for: .normal)

let selectedAttrib: [NSAttributedString.Key : Any] = [.font : UIFont(family: .medium, ofSize: 13)!, .foregroundColor : UIColor.red]
segmentControl.setTitleTextAttributes(hightLightedStateAttrib, for: .selected)

注意:我在谷歌上搜索了很长时间,这就是我发布在这里的原因。

来源:CodeMentor

  • 已接受的答案适用于消除边框。
  • 提到的解决方案here也适用于禁用分段控件。

然而,将两个解决方案放在一起,我无法在 disabled 状态下获得正确的 selected 段。

我想要的是在选择段并进行网络调用时,我想禁用分段控制。

结果是这样的:

想要的是:

的唯一补充是:

setBackgroundImage(imageWithColor(color: imageWithColor(color: tintColor)), for: [.selected, .disabled], barMetrics: .default)

选择&&禁用后段将具有正确的颜色。

Swift 5.x:

此解决方案仅删除外部边框并保留每个按钮上的圆角

extension UISegmentedControl {
    func removeBorders(andBackground:Bool=false) {
        setBackgroundImage(imageWithColor(color: backgroundColor ?? .clear), for: .normal, barMetrics: .default)
        setBackgroundImage(imageWithColor(color: tintColor!), for: .selected, barMetrics: .default)
        setDividerImage(imageWithColor(color: UIColor.clear), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)

        _ = self.subviews.compactMap {
            if ([=10=].frame.width>0) {
                [=10=].layer.cornerRadius = 8
                [=10=].layer.borderColor = UIColor.clear.cgColor
                [=10=].clipsToBounds = true
                [=10=].layer.borderWidth = andBackground ? 1.0 : 0.0
                [=10=].layer.borderColor = andBackground ? tintColor?.cgColor : UIColor.clear.cgColor
                andBackground ? [=10=].layer.backgroundColor = UIColor.clear.cgColor : nil
            }
        }
    }

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

用法:

mySegmentedControl.removeBorders()

对我有帮助。

但是如果不设置UIImage大小,可能会影响UISegmentedControl的大小。

如果您也遇到这个问题,请考虑使用下面的代码。

func *(lhs: CGSize, rhs: CGFloat) -> CGSize {
    return CGSize(width: lhs.width * rhs, height: lhs.height * rhs)
}

extension UIImage {
    func resized(_ size: CGSize) -> UIImage? {
        defer { UIGraphicsEndImageContext() }
        UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
        self.draw(in: CGRect(origin: .zero, size: size))
        return UIGraphicsGetImageFromCurrentImageContext()
    }

    func resized(_ size: CGFloat) -> UIImage? {
        guard size > 0, self.size.width > 0, self.size.height > 0 else { return nil }
        let ratio = size / max(self.size.width, self.size.height)
        return self.resized(self.size * ratio)
    }

    func refilled(_ color: UIColor) -> UIImage? {
        defer { UIGraphicsEndImageContext() }
        UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
        color.set()
        UIGraphicsGetCurrentContext()?.fill(CGRect(origin: .zero, size: self.size))
        return UIGraphicsGetImageFromCurrentImageContext()
    }

    public convenience init?(color: UIColor = .clear, size: CGSize) {
        defer { UIGraphicsEndImageContext() }
        UIGraphicsBeginImageContext(size)

        guard let context = UIGraphicsGetCurrentContext() else { return nil }
        context.setFillColor(color.cgColor);
        context.fill(CGRect(origin: .zero, size: size));
        guard let cgImage = UIGraphicsGetImageFromCurrentImageContext()?.cgImage else { return nil }

        self.init(cgImage: cgImage)
    }
}

extension UISegmentedControl {
    func removeBorders() {
        let image = UIImage(size: self.bounds.size)
        self.setBackgroundImage(image, for: .normal, barMetrics: .default)
        self.setBackgroundImage(image?.refilled(self.tintColor), for: .selected, barMetrics: .default)
        self.setDividerImage(image?.resized(1), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
    }
}

易于使用:

segmentedControl.removeBorders()