J'essaie de définir les propriétés de la couche d'une vue via IB. Tout fonctionne sauf la couleur de la bordure (property layer.borderColor
):
Je me rappelle avoir rencontré ce problème il y a un an et je l'ai finalement fait par programme. Et encore, je peux le faire par programme, mais je suis curieux de savoir pourquoi la propriété layer.borderColor
ne fonctionne jamais via le constructeur d'interface. Je ne veux pas importer QuartzCore
, puis écrire une ligne de code supplémentaire simplement à cause de cela, cela semble excessif.
C'est possible, mais ce n'est pas une fonctionnalité intégrée. En effet, le type Color
du panneau Attributs d'exécution définis par l'utilisateur crée une variable UIColor
, mais layer.borderColor
contient un type CGColorRef
. Malheureusement, il n'existe aucun moyen d'attribuer un type CGColorRef
dans Interface Builder.
Cependant, cela est possible via une propriété proxy. Voir Réponse de Peter DeWeese à une autre question pour une solution possible à ce problème. Sa réponse définit une catégorie permettant de définir une couleur de proxy via Interface Builder.
Vous devez créer une catégorie pour CALayer:
CALayer + UIColor.h
#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>
@interface CALayer(UIColor)
// This assigns a CGColor to borderColor.
@property(nonatomic, assign) UIColor* borderUIColor;
@end
CALayer + UIColor.m
#import "CALayer+UIColor.h"
@implementation CALayer(UIColor)
- (void)setBorderUIColor:(UIColor*)color {
self.borderColor = color.CGColor;
}
- (UIColor*)borderUIColor {
return [UIColor colorWithCGColor:self.borderColor];
}
@end
Et ensuite dans Attributs d'exécution définis par l'utilisateur Vous pouvez l'utiliser tel quel sur l'image ci-dessous:
Pour Swift c'est beaucoup plus simple:
@IBInspectable var borderColor: UIColor? {
didSet {
layer.borderColor = borderColor?.CGColor
layer.borderWidth = 1
}
}
Ensuite, dans Xcode, vous pouvez l'utiliser comme ceci:
Une fois choisi, il est automatiquement ajouté à vos attributs d'exécution :
Mes deux cents pour porter la réponse de Bartłomiej Semańczyk à Swift:
Créez une extension pour CALayer dans votre contrôleur de vue:
import UIKit
extension CALayer {
func borderUIColor() -> UIColor? {
return borderColor != nil ? UIColor(CGColor: borderColor!) : nil
}
func setBorderUIColor(color: UIColor) {
borderColor = color.CGColor
}
}
Copiez et collez cette classe:
import UIKit
@IBDesignable class BorderView : UIView {
@IBInspectable var borderColor: UIColor = .clear {
didSet {
layer.borderColor = borderColor.cgColor
}
}
@IBInspectable var borderWidth: CGFloat = 0 {
didSet {
layer.borderWidth = borderWidth
}
}
@IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
}
}
}
Maintenant, dans Interface Builder, accédez à l'inspecteur d'identité et définissez votre vue en tant que classe CustomView.
Après cela, vérifiez votre inspecteur d'attributs:
Plus besoin de perdre son temps avec les attributs d'exécution définis par l'utilisateur. Et vos modifications apparaîtront également sur la toile!
Utilisez IBDesignable au lieu d’attributs d’exécution, c’est plus clair.
Placez ce code dans n'importe quelle classe et modifiez les propriétés directement sur le storyboard.
import UIKit
@IBDesignable extension UIView {
@IBInspectable var borderColor:UIColor? {
set {
layer.borderColor = newValue!.CGColor
}
get {
if let color = layer.borderColor {
return UIColor(CGColor:color)
}
else {
return nil
}
}
}
@IBInspectable var borderWidth:CGFloat {
set {
layer.borderWidth = newValue
}
get {
return layer.borderWidth
}
}
@IBInspectable var cornerRadius:CGFloat {
set {
layer.cornerRadius = newValue
clipsToBounds = newValue > 0
}
get {
return layer.cornerRadius
}
}
}
Voici un moyen rapide de surmonter cela. Catégories ...
@interface UIView (IBAppearance)
@property (nonatomic, strong) UIColor *borderColor;
@end
Vous n'êtes pas obligé de le stocker, c'est juste Nice pour pouvoir interroger plus tard. L'important est de prendre la valeur et d'attribuer la CGColor de UIColor à la couche.
#import <objc/runtime.h>
#define BORDER_COLOR_KEYPATH @"borderColor"
@implementation UIView (IBAppearance)
- (void)setBorderColor:(UIColor *)borderColor {
UIColor *bc = objc_getAssociatedObject(self, BORDER_COLOR_KEYPATH);
if(bc == borderColor) return;
else {
objc_setAssociatedObject(self, BORDER_COLOR_KEYPATH, borderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
self.layer.borderColor = [borderColor CGColor];
}
}
- (UIColor *)borderColor {
return objc_getAssociatedObject(self, BORDER_COLOR_KEYPATH);
}
@end
Bien sûr, dans Interface Builder, vous ne définissez pas la valeur sur layer.borderColor
, mais simplement sur borderColor
.
Dans Swift, vous pouvez étendre la classe UIButton
et ajouter un @IBInspectable
qui vous permettra de sélectionner une couleur dans le storyboard et de définir sa couleur (avec une largeur de 1 pouvant être modifiée) . Ajoutez-le à la fin de votre contrôleur de vue. :
extension UIButton{
@IBInspectable var borderColor: UIColor? {
get {
return UIColor(CGColor: layer.borderColor!)
}
set {
layer.borderColor = newValue?.CGColor
layer.borderWidth = 1
}
}
}
Pour que CALayer KVC soit conforme à la propriété borderColorFromUIColor, implémentez simplement
layer.borderColorFromUIColor=[UIColor red];
J'ai rencontré le même problème, j'ai résolu ce problème en créant une classe de boutons personnalisée:
class UIButtonWithRoundBorder: UIButton {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.layer.cornerRadius = 6
self.layer.borderWidth = 1
self.layer.borderColor = UIColor.whiteColor().CGColor
self.clipsToBounds = true
}
}
Ensuite, dans IB, remplacez le type "UIButton" par "UIButtonWithRoundBorder".
Simple et pratique aussi. :)
Swift4
extension CALayer {
open override func setValue(_ value: Any?, forKey key: String) {
/// If key is borderColor, and the value is the type of a UIColor.
if key == "borderColor" , let color = value as? UIColor {
/// After converting UIColor to CGColor, call the system method.
return super.setValue(color.cgColor, forKey: key)
}
super.setValue(value, forKey: key)
}
}
Vous pouvez définir une valeur pour la clé "borderColor" dans le fichier XIB et utiliser:
extension UIView {
open override func setValue(_ value: Any?, forKey key: String) {
guard key == "borderColor", let color = value as? UIColor else {
super.setValue(value, forKey: key)
return
}
layer.borderColor = color.cgColor
}
}
borderColor
ne fonctionnera pas SAUF si la propriété borderWidth
du calque est définie sur une valeur supérieure à 0 .
Swift 3:
button.layer.borderColor = UIColor.white.cgColor
button.layer.borderWidth = 1.0 // Default value is 0, that's why omitting this line will not make the border color show.
Vous pouvez personnaliser la bordure avec 2 méthodes ..___ La première est la suivante. Il suffit de cliquer sur l'objet pour accéder à l'inspecteur d'identité et définir les attributs.
La seconde est la suivante. faire un objet requis IBOutlet et mettre ce code en vue ne se charge.
@IBOutlet weak var uploadView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
uploadView.layer.cornerRadius = 10
uploadView.layer.borderWidth = 1.0
uploadView.layer.borderColor = #colorLiteral(red: 0.08235294118, green: 0.5058823529, blue: 0.9450980392, alpha: 1)
}
Je pense que c'est peut-être parce que vous avez défini les masquesToBounds sur OUI. Je ne pense pas que la frontière soit tracée dans les limites de la couche, elle ne sera donc pas tracée puisque vous cachez tout en dehors de ses limites