Ich versuche, die Layer-Eigenschaften einer Ansicht über IB einzurichten. Alles funktioniert außer der Farbe des Rahmens (Eigenschaft layer.borderColor
):
Ich erinnere mich, dass ich vor einem Jahr auf dieses Problem gestoßen bin und es am Ende programmatisch gemacht habe. Und ich kann das zwar programmgesteuert machen, aber ich bin neugierig, warum die layer.borderColor
-Eigenschaft niemals über den Interface Builder funktioniert. Ich möchte QuartzCore
nicht importieren und schreibe aus diesem Grund eine zusätzliche Codezeile, die wie ein Overkill wirkt.
Dies ist möglich, aber es ist keine integrierte Funktion. Dies liegt daran, dass der Typ Color
im Bedienfeld Benutzerdefinierte Laufzeitattribute einen UIColor
erstellt, aber layer.borderColor
einen CGColorRef
-Typ enthält. Leider kann im Interface Builder kein CGColorRef
-Typ zugewiesen werden.
Dies ist jedoch über eine Proxy-Eigenschaft möglich. Siehe Peter DeWeeses Antwort auf eine andere Frage, um eine mögliche Lösung für dieses Problem zu finden. Seine Antwort definiert eine Kategorie, in der eine Proxy-Farbe über den Interface Builder festgelegt werden kann.
Sie müssen eine Kategorie für CALayer erstellen:
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
Und dann in Benutzerdefinierte Laufzeitattribute Sie können es wie in der Abbildung unten verwenden:
Für Swift ist es viel einfacher:
@IBInspectable var borderColor: UIColor? {
didSet {
layer.borderColor = borderColor?.CGColor
layer.borderWidth = 1
}
}
Dann können Sie es in Xcode folgendermaßen verwenden:
Sobald Sie sich für etw entschieden haben, wird es automatisch zu Ihren Laufzeitattributen hinzugefügt :
Meine zwei Cent für die Portierung von Bartłomiej Semańczyks Antwort auf Swift:
Erstellen Sie eine Erweiterung für CALayer in Ihrem View-Controller:
import UIKit
extension CALayer {
func borderUIColor() -> UIColor? {
return borderColor != nil ? UIColor(CGColor: borderColor!) : nil
}
func setBorderUIColor(color: UIColor) {
borderColor = color.CGColor
}
}
Kopieren Sie diese Klasse und fügen Sie sie ein:
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
}
}
}
Wechseln Sie nun im Interface Builder zum Identitätsinspektor und legen Sie Ihre Ansicht als CustomView-Klasse fest.
Überprüfen Sie anschließend Ihren Attribut-Inspektor:
Sie müssen sich nicht mehr mit benutzerdefinierten Laufzeitattributen herumschlagen. Und Ihre Änderungen werden auch auf der Leinwand angezeigt!
Verwenden Sie IBDesignable anstelle von Laufzeitattributen. Dies ist klarer.
Fügen Sie diesen Code in eine beliebige Klasse ein und bearbeiten Sie die Eigenschaften direkt im 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
}
}
}
Hier ist ein schneller Weg, um dies zu überwinden. Kategorien...
@interface UIView (IBAppearance)
@property (nonatomic, strong) UIColor *borderColor;
@end
Sie müssen es nicht speichern, es ist nur Nizza, so dass Sie später abfragen können. Das Wichtigste ist, den Wert zu übernehmen und die CGColor des UIColors der Ebene zuzuweisen.
#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
Natürlich setzen Sie im Interface Builder den Wert nicht auf layer.borderColor
, sondern nur auf borderColor
.
In Swift können Sie die UIButton
-Klasse erweitern und einen @IBInspectable
hinzufügen, mit dem Sie eine Farbe aus dem Storyboard auswählen und deren Farbe festlegen können (mit der Breite 1, die geändert werden kann). _ Fügen Sie diese am Ende Ihres View-Controllers hinzu :
extension UIButton{
@IBInspectable var borderColor: UIColor? {
get {
return UIColor(CGColor: layer.borderColor!)
}
set {
layer.borderColor = newValue?.CGColor
layer.borderWidth = 1
}
}
}
Um CALayer KVC-kompatibel für die Eigenschaft borderColorFromUIColor zu machen, implementieren Sie einfach das
layer.borderColorFromUIColor=[UIColor red];
Ich habe das gleiche Problem kennengelernt und bin damit umgegangen, indem ich eine benutzerdefinierte Button-Klasse erstellt habe:
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
}
}
Ändern Sie dann in IB den Typ von "UIButton" in "UIButtonWithRoundBorder".
Einfach und praktisch auch. :)
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)
}
}
Sie können einen Wert für den Schlüssel "borderColor" in der XIB festlegen und verwenden:
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
funktioniert nicht, WENN die borderWidth
-Eigenschaft des Layers auf einen Wert größer als 0 gesetzt ist.
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.
Sie können den Rahmen mit 2 Methoden anpassen .. _. Klicken Sie einfach auf das Objekt, gehen Sie zum Identitätsinspektor und legen Sie die Attribute fest.
Der zweite ist dies. Erstellen Sie ein IBOutlet des erforderlichen Objekts und setzen Sie diesen Code in die Ansicht, dass er geladen wurde.
@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)
}
Ich denke, das kann daran liegen, dass Sie maskenToBounds auf YES gesetzt haben. Ich denke nicht, dass die Grenze innerhalb der Grenzen der Ebene gezeichnet wird, also wird sie nicht gezeichnet, da Sie alles außerhalb der Grenzen verbergen.