如何在Swift中使按钮具有圆形边框?

Gui*_*i23 220 uibutton swift

我正在使用最新版本的Xcode 6中的swift构建应用程序,并想知道如何修改我的按钮,以便它可以有一个圆形边框,我可以根据需要调整自己.完成后,如何在不添加背景的情况下更改边框颜色?换句话说,我想要一个没有背景的略微圆角的按钮,只有一个特定颜色的1pt边框.

ret*_*rue 497

使用button.layer.cornerRadius,button.layer.borderColorbutton.layer.borderWidth.注意,borderColor需要一个CGColor,所以你可以说(Swift 3/4):

button.backgroundColor = .clear
button.layer.cornerRadius = 5
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor
Run Code Online (Sandbox Code Playgroud)

  • 我尝试了这个,但是我有一个小问题,第一个文本是从边框本身开始的,所以它不是那么好看有没有办法解决这个问题 (2认同)
  • @ vinbhai4u尝试使用`titleEdgeInsets`。 (2认同)

Fan*_*ing 55

在storyboard中完成此工作(Interface Builder Inspector)

借助于IBDesignable我们,我们可以为Interface Builder Inspector添加更多选项,UIButton并在故事板上进行调整.首先,将以下代码添加到项目中.

@IBDesignable extension UIButton {

    @IBInspectable var borderWidth: CGFloat {
        set {
            layer.borderWidth = newValue
        }
        get {
            return layer.borderWidth
        }
    }

    @IBInspectable var cornerRadius: CGFloat {
        set {
            layer.cornerRadius = newValue
        }
        get {
            return layer.cornerRadius
        }
    }

    @IBInspectable var borderColor: UIColor? {
        set {
            guard let uiColor = newValue else { return }
            layer.borderColor = uiColor.cgColor
        }
        get {
            guard let color = layer.borderColor else { return nil }
            return UIColor(cgColor: color)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后只需在故事板上设置按钮的属性.

在此输入图像描述

  • 这或多或少是以下Hamza Ghazouani答案的副本。 (4认同)

sgi*_*gib 22

我已经创建了一个简单的UIButton sublcass,它使用了tintColor它的文本和边框颜色,并在突出显示时将其背景更改为tintColor.

class BorderedButton: UIButton {

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    layer.borderWidth = 1.0
    layer.borderColor = tintColor.CGColor
    layer.cornerRadius = 5.0
    clipsToBounds = true
    contentEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
    setTitleColor(tintColor, forState: .Normal)
    setTitleColor(UIColor.whiteColor(), forState: .Highlighted)
    setBackgroundImage(UIImage(color: tintColor), forState: .Highlighted)
}
}
Run Code Online (Sandbox Code Playgroud)

这使用了一个从颜色创建图像的UIImage扩展,我在这里找到了代码:https://stackoverflow.com/a/33675160

当设置为在界面构建器中键入自定义时,它最有效,因为默认系统类型会在突出显示按钮时稍微修改颜色.


Gia*_*ang 14

@IBOutlet weak var yourButton: UIButton! {
    didSet{
        yourButton.backgroundColor = .clear
        yourButton.layer.cornerRadius = 10
        yourButton.layer.borderWidth = 2
        yourButton.layer.borderColor = UIColor.white.cgColor
    }
}
Run Code Online (Sandbox Code Playgroud)


le0*_*iaz 13

本课程基于答案中的所有评论和建议,也可以直接从xcode设计.复制到您的项目并插入任何UIButton并更改为使用自定义类,现在只需从xcode中选择正常和/或突出显示状态的边框或背景颜色.

//
//  RoundedButton.swift
//

import UIKit

@IBDesignable
class RoundedButton:UIButton {

    @IBInspectable var borderWidth: CGFloat = 0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }
    //Normal state bg and border
    @IBInspectable var normalBorderColor: UIColor? {
        didSet {
            layer.borderColor = normalBorderColor?.CGColor
        }
    }

    @IBInspectable var normalBackgroundColor: UIColor? {
        didSet {
            setBgColorForState(normalBackgroundColor, forState: .Normal)
        }
    }


    //Highlighted state bg and border
    @IBInspectable var highlightedBorderColor: UIColor?

    @IBInspectable var highlightedBackgroundColor: UIColor? {
        didSet {
            setBgColorForState(highlightedBackgroundColor, forState: .Highlighted)
        }
    }


    private func setBgColorForState(color: UIColor?, forState: UIControlState){
        if color != nil {
            setBackgroundImage(UIImage.imageWithColor(color!), forState: forState)

        } else {
            setBackgroundImage(nil, forState: forState)
        }
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        layer.cornerRadius = layer.frame.height / 2
        clipsToBounds = true

        if borderWidth > 0 {
            if state == .Normal && !CGColorEqualToColor(layer.borderColor, normalBorderColor?.CGColor) {
                layer.borderColor = normalBorderColor?.CGColor
            } else if state == .Highlighted && highlightedBorderColor != nil{
                layer.borderColor = highlightedBorderColor!.CGColor
            }
        }
    }

}

//Extension Required by RoundedButton to create UIImage from UIColor
extension UIImage {
    class func imageWithColor(color: UIColor) -> UIImage {
        let rect: CGRect = CGRectMake(0, 0, 1, 1)
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(1, 1), false, 1.0)
        color.setFill()
        UIRectFill(rect)
        let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}
Run Code Online (Sandbox Code Playgroud)


Zvi*_*Zvi 9

基于@returntrue的答案,我设法在Interface Builder中实现它.

要使用Interface Builder获取圆角按钮,请在按钮的" "中添加一个Path = "layer.cornerRadius"带有Type = "Number"Value = "10"(和其他所需值)的按键.User Defined RunTime AttributeIdentity Inspector

  • 我的回答不是针对OP,而是针对其他遇到我问题的读者。而且只有找到这篇文章才能解决问题。以我的观点和经验,答案并不完全是OP所要求的,只要它们与OP相关并且能提供对读者有用的额外信息即可。通过对这样的答案投反对票,您会阻止有用的答案。 (2认同)

Nik*_*Jha 7

您可以使用 UIButton 的这个子类来根据您的需要自定义 UIButton。

访问此 github repo 以供参考

class RoundedRectButton: UIButton {

    var selectedState: Bool = false

    override func awakeFromNib() {
        super.awakeFromNib()
        layer.borderWidth = 2 / UIScreen.main.nativeScale
        layer.borderColor = UIColor.white.cgColor
        contentEdgeInsets = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
    }


    override func layoutSubviews(){
        super.layoutSubviews()
        layer.cornerRadius = frame.height / 2
        backgroundColor = selectedState ? UIColor.white : UIColor.clear
        self.titleLabel?.textColor = selectedState ? UIColor.green : UIColor.white
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        selectedState = !selectedState
        self.layoutSubviews()
    }
}
Run Code Online (Sandbox Code Playgroud)


Ham*_*mza 5

我认为最简单、最干净的方法是使用协议来避免继承和代码重复。您可以直接从故事板更改此属性

protocol Traceable {
    var cornerRadius: CGFloat { get set }
    var borderColor: UIColor? { get set }
    var borderWidth: CGFloat { get set }
}

extension UIView: Traceable {

    @IBInspectable var cornerRadius: CGFloat {
        get { return layer.cornerRadius }
        set {
            layer.masksToBounds = true
            layer.cornerRadius = newValue
        }
    }

    @IBInspectable var borderColor: UIColor? {
        get {
            guard let cgColor = layer.borderColor else { return nil }
            return  UIColor(cgColor: cgColor)
        }
        set { layer.borderColor = newValue?.cgColor }
    }

    @IBInspectable var borderWidth: CGFloat {
        get { return layer.borderWidth }
        set { layer.borderWidth = newValue }
    }
}
Run Code Online (Sandbox Code Playgroud)

更新

在此链接中,您可以找到使用 Traceable 协议的示例

在此输入图像描述

  • 您实际上并不需要这里的协议。没有它也能完全正常工作。 (2认同)
  • 嗨@returntrue,我不知道你为什么对我的答案投反对票...我认为你没有理解它,我邀请你观看本次会议:https://developer.apple.com/videos/play/wwdc2015/408 / 为什么使用协议?协议允许更大的灵活性,我可以有默认实现等我的答案允许在故事板中编辑此属性,并且我不需要重复代码或子类任何类你的答案是正确的,但在这里我分享了另一种方法你对所有其他答案都投了反对票,你应该记住,Stackoverflow 是为了在赢得声誉之前分享我们的知识 (2认同)
  • 正确,您的代码允许您列出的所有这些内容。但是,由于 UIView 是所有 UI 元素的超类,因此您的 UIView 扩展足以完成这项工作。Traceable 协议不是以任何方式需要的,也不会产生任何改进(因为它只是转换为 UIView - 只有 UIView 及其子类是可跟踪的)。 (2认同)