Je construis une application à l'aide de Swift dans la dernière version de Xcode 6 et j'aimerais savoir comment je peux modifier mon bouton afin qu'il puisse avoir une bordure arrondie que je pourrais ajuster si nécessaire. Une fois cela fait, comment puis-je changer la couleur de la bordure sans ajouter d'arrière-plan? En d'autres termes, je veux un bouton légèrement arrondi sans arrière-plan, seulement une bordure de 1 pt d'une certaine couleur.
Utilisez button.layer.cornerRadius
, button.layer.borderColor
et button.layer.borderWidth
. Notez que borderColor
requiert une CGColor
, donc vous pourriez dire (Swift 3/4):
button.backgroundColor = .clear
button.layer.cornerRadius = 5
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor
Effectuer ce travail dans le storyboard (Interface Builder Inspector)
Avec l’aide de IBDesignable
, nous pouvons ajouter d’autres options à Interface Builder Inspector for UIButton
et les ajuster sur le storyboard. Tout d’abord, ajoutez le code suivant à votre projet.
@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)
}
}
}
Ensuite, définissez simplement les attributs des boutons sur le storyboard.
J'ai créé une sous-classe UIButton simple qui utilise la variable tintColor
pour le texte et les couleurs de la bordure. Lorsque l'arrière-plan est mis en surbrillance, son arrière-plan devient la 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)
}
}
Cela utilise une extension UIImage qui crée une image à partir d’une couleur. J’ai trouvé ce code ici: https://stackoverflow.com/a/33675160
Cela fonctionne mieux lorsque vous définissez le type Personnalisé dans le générateur d'interface, car le type de système par défaut modifie légèrement les couleurs lorsque le bouton est en surbrillance.
Cette classe est basée sur tous les commentaires et suggestions des réponses, et peut également être conçue directement à partir de xcode. Copiez dans votre projet et insérez n'importe quel UIButton et utilisez une classe personnalisée. Il vous suffit maintenant de sélectionner la couleur de bordure ou d'arrière-plan dans xcode pour les états normaux et/ou en surbrillance.
//
// 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
}
}
Basé sur @returntrue answer, j'ai réussi à l'implémenter dans Interface Builder.
Pour obtenir le bouton coins arrondis à l'aide d'Interface Builder, ajoutez une clé Path = "layer.cornerRadius"
avec Type = "Number"
et Value = "10"
(ou toute autre valeur requise) dans le "User Defined RunTime Attribute
" du Identity Inspector
du bouton.
Vous pouvez utiliser cette sous-classe d'UIButton pour personnaliser UIButton selon vos besoins.
visitez ce dépôt Github pour référence
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()
}
}
@IBOutlet weak var yourButton: UIButton! {
didSet{
yourButton.backgroundColor = .clear
yourButton.layer.cornerRadius = 10
yourButton.layer.borderWidth = 2
yourButton.layer.borderColor = UIColor.white.cgColor
}
}
Je pense que le moyen le plus simple et le plus propre consiste à utiliser un protocole pour éviter les héritages et la répétition de code .. Vous pouvez modifier ces propriétés directement à partir du storyboard
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 }
}
}
Mettre à jour
Dans ce link vous pouvez trouver un exemple avec l’utilité du protocole Traceable
ESSAYEZ CECI Bordure à boutons aux coins arrondis
anyButton.backgroundColor = .clear
anyButton.layer.cornerRadius = anyButton.frame.height / 2
anyButton.layer.borderWidth = 1
anyButton.layer.borderColor = UIColor.black.cgColor
astuce à part assurez-vous que votre bouton n'est pas une sous-classe d'une classe personnalisée dans le story-board, dans ce cas, votre meilleur emplacement de code devrait être dans la classe personnalisée. La classe UIButton et son exutoire, espérons que cela puisse aider quelqu'un à se demander pourquoi les radios de coin ne s'appliquent pas sur mon bouton à partir du code.
@IBOutlet weak var button: UIButton!
...
Je pense que pour le rayon juste ce paramètre:
button.layer.cornerRadius = 5