Ist es möglich, UIView-Randeigenschaften über den Interface Builder festzulegen?

184

Ist es möglich, die Eigenschaften von UIView-Rändern (Farbe, Dicke usw.) direkt vom Interface Builder aus zu steuern, oder kann ich dies nur programmgesteuert tun?

matteo.cajani
quelle
Überprüfen Sie diese http://stackoverflow.com/a/28854514/3177007
Mohamed Jaleel Nazir
1
Nur für den Fall, dass jemand wie ich von Google kommt. Um zu sehen, wie sich diese Änderungen in IB widerspiegeln, müssen Sie nur eine Unterklasse von UIView erstellen und sie jeder Ansicht zuweisen, die Sie in IB bearbeiten möchten.
Kanongata

Antworten:

393

Tatsächlich können Sie einige Eigenschaften der Ebene einer Ansicht über den Interface Builder festlegen. Ich weiß, dass ich die Rahmenbreite und den Eckradius einer Ebene über xcode festlegen kann. borderColor funktioniert nicht, wahrscheinlich weil die Ebene eine CGColor anstelle einer UIColor möchte.

Möglicherweise müssen Sie Strings anstelle von Zahlen verwenden, aber es funktioniert!

layer.cornerRadius
layer.borderWidth
layer.borderColor

Update: layer.masksToBounds = true

Beispiel

Update: Wählen Sie den entsprechenden Typ für den Schlüsselpfad aus:

Geben Sie hier die Bildbeschreibung ein

Rich86man
quelle
3
An Sie und Peter DeWeese: Ich verwende Xcode 4.6.3 und kann den Schlüsselpfadtyp auf "Farbe" setzen, ohne eine CALayer-Schnittstelle zu implementieren
39
Leider kann layer.borderColor nicht auf diese Weise eingestellt werden. Es ist ein CGColorRef, aber dieser IB-Farbwerttyp ist eine UIColor.
Mrgrieves
12
Dies ist also, was die benutzerdefinierten Laufzeitattribute tun! Haha, ich schreibe seit 2011 für iOS und habe nie erfahren, wofür diese Felder gedacht sind. Danke für diese tolle Antwort.
Andy Ibanez
3
Schön, aber Sie müssen für jede Eigenschaft den richtigen Typ festlegen. Der Typ für zB "layer.cornerRadius" muss auf "Number" anstelle von "String" gesetzt werden!
Peter Kreinz
5
Vergessen Sie auch nicht, das Kontrollkästchen "Clip to Bounds" zu aktivieren, damit der CornerRadius funktioniert.
Pierre-Olivier Simonard
182

Die Antwort von Rich86Man ist korrekt, aber Sie können Kategorien verwenden, um Eigenschaften wie layer.borderColor zu vertreten. (Vom konventionellen C CocoaPod)

CALayer + XibConfiguration.h:

#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>

@interface CALayer(XibConfiguration)

// This assigns a CGColor to borderColor.
@property(nonatomic, assign) UIColor* borderUIColor;

@end

CALayer + XibConfiguration.m:

#import "CALayer+XibConfiguration.h"

@implementation CALayer(XibConfiguration)

-(void)setBorderUIColor:(UIColor*)color
{
    self.borderColor = color.CGColor;
}

-(UIColor*)borderUIColor
{
    return [UIColor colorWithCGColor:self.borderColor];
}

@end

Interface Builder

layer.borderUIColor

Das Ergebnis wird zur Laufzeit angezeigt, nicht in Xcode.

Bearbeiten : Sie müssen außerdem layer.borderWidthmindestens 1 festlegen , um den Rand mit der ausgewählten Farbe anzuzeigen.

In Swift 2.0:

extension CALayer {
    var borderUIColor: UIColor {
        set {
            self.borderColor = newValue.CGColor
        }

        get {
            return UIColor(CGColor: self.borderColor!)
        }
    }
}

In Swift 3.0:

extension CALayer {
    var borderUIColor: UIColor {
        set {
            self.borderColor = newValue.cgColor
        }

        get {
            return UIColor(cgColor: self.borderColor!)
        }
    }
}
Peter DeWeese
quelle
Ich kann das nicht für mich arbeiten lassen. Die .m-Datei stöhnt darüber, dass borderColor borderUIColor sein und behoben werden muss. Danach werden weiterhin Warnungen angezeigt und die Rahmenfarbe wird zur Laufzeit nicht gerendert. Das Bit, das bei mir anders ist, ist, dass ich @ Implementation NameOfFile habe, nicht @ Implementation CALayer (NameOfFile). Ich verstehe den CALayer-Teil nicht. Könnten Sie das bitte näher erläutern?
Dave Haigh
2
@ PeterDeWeese tolle Antwort! =)
C-Bösewicht
1
Sie können Number tatsächlich mit borderWidth verwenden und eine NSNumber akzeptieren. Es funktioniert gut.
Peter DeWeese
1
Dies ist meiner Meinung nach definitiv die beste Lösung, um das Problem von BorderColor zu lösen. Fantastische Verwendung von Kategorien!
EricWasTaken
1
Arbeitete in Swift!
KOTIOS
81

Ähnliche Antwort zu iHulks, aber in Swift

Fügen Sie Ihrem Projekt eine Datei mit dem Namen UIView.swift hinzu (oder fügen Sie diese einfach in eine beliebige Datei ein):

import UIKit

@IBDesignable extension UIView {
    @IBInspectable var borderColor: UIColor? {
        set {
            layer.borderColor = newValue?.cgColor
        }
        get {
            guard let color = layer.borderColor else {
                return nil
            }
            return UIColor(cgColor: color)
        }
    }
    @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
        }
    }
}

Dies ist dann im Interface Builder für jede Schaltfläche, Bildansicht, Beschriftung usw. im Dienstprogrammbedienfeld> Attributinspektor verfügbar:

Attributinspektor

Hinweis: Der Rahmen wird nur zur Laufzeit angezeigt.

Axel Guilmin
quelle
@ Gaurav Welchen Fehler sehen Sie? Auf welcher Komponente (UIButton, UILabel usw.) verwenden Sie sie?
Axel Guilmin
Ich kann Ihnen nicht ohne weitere Details helfen :(
Axel Guilmin
2
Bei diesem Ansatz kam es zu Abstürzen des Interface Builder, bis ich ihn @IBDesignablevom Anfang der Erweiterung entfernte.
Albert Bori
1
Das ist unglaublich ... Danke! Ich benutze XCode 8.2.1
Bobwki
1
Sehr praktisch und ordentlich! Vielen Dank!
Karl-John Chow
56

Sie können eine Kategorie von UIView erstellen und diese in die .h-Datei der Kategorie einfügen

@property (nonatomic) IBInspectable UIColor *borderColor;
@property (nonatomic) IBInspectable CGFloat borderWidth;
@property (nonatomic) IBInspectable CGFloat cornerRadius;

Fügen Sie dies nun in die .m-Datei ein

@dynamic borderColor,borderWidth,cornerRadius;

und das auch in. m Datei

-(void)setBorderColor:(UIColor *)borderColor{
    [self.layer setBorderColor:borderColor.CGColor];
}

-(void)setBorderWidth:(CGFloat)borderWidth{
    [self.layer setBorderWidth:borderWidth];
}

-(void)setCornerRadius:(CGFloat)cornerRadius{
    [self.layer setCornerRadius:cornerRadius];
}

Jetzt sehen Sie dies in Ihrem Storyboard für alle UIView-Unterklassen (UILabel, UITextField, UIImageView usw.)

Geben Sie hier die Bildbeschreibung ein

Das ist es .. Keine Notwendigkeit, eine Kategorie irgendwo zu importieren, fügen Sie einfach die Dateien der Kategorie im Projekt hinzu und sehen Sie diese Eigenschaften im Storyboard.

iHulk
quelle
2
Ergänzen Sie es mit IB_DESIGNABLE, damit IB Ihre benutzerdefinierte Ansicht mit der drawRect neu zeichnet: method developer.apple.com/library/ios/recipes/…
txulu
3
Das ist großartig, wenn Sie IB_DESIGNABLE in die .h-Datei vor der Schnittstellenzeile schreiben, müssen Sie keine @dynamic-Zeile in .m
Jasmeet
@ user1618612 es hat nichts mit der Auflösung zu tun, es setzt nur normale Ebeneneigenschaften.
iHulk
11

Für Swift 3 und 4 gibt es Folgendes, wenn Sie bereit sind, IBInspectables zu verwenden :

@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
        }
    }
}
RamwiseMatt
quelle
Dies ist die beste Lösung für mich
Mục Đồng
Tolle Lösung, danke u
Ebtehal___
7

Dies kann zwar die Eigenschaften festlegen, spiegelt sich jedoch nicht in IB wider. Wenn Sie also im Wesentlichen Code in IB schreiben, können Sie dies auch in Ihrem Quellcode tun

Zayin Krige
quelle
1
Willkommen bei MVC! Sie sehen Eigenschaften sollten niemals im Code sein!
Alejandro Iván
2
^ Dies ist nicht das, was MVC ist.
Andrew Plummer
1
Wenn man bedenkt, dass dieser Code zu 95% in der Steuerung gespeichert ist, ist er auch MVC. Wenn Sie Ihre Ansicht ordnungsgemäß unterordnen oder erweitern, ist dies nur eine Konfiguration über die Codierung :-)
Daniele Bernardini
4

Wenn Sie Zeit sparen möchten, verwenden Sie einfach zwei UIViewsübereinander, wobei die hintere die Rahmenfarbe und die vordere kleinere Farbe ist, um den Randeffekt zu erzielen. Ich denke auch nicht, dass dies eine elegante Lösung ist, aber wenn Apple sich ein bisschen mehr darum kümmert, sollten Sie dies nicht tun müssen.

Matthew Quiros
quelle
10
Problemumgehungen sparen jetzt Zeit und verschwenden in Zukunft viel mehr Zeit.
Lachezar Todorov
0

Es ist absolut nur möglich, wenn Sie layer.masksToBounds = trueSachen einstellen und ausruhen.

Sunil Targe
quelle
-1

Das Storyboard funktioniert bei mir nicht immer, selbst nachdem ich die gesamte Lösung hier ausprobiert habe

Es ist also immer die perfekte Antwort, den Code zu verwenden. Erstellen Sie einfach eine IBOutlet-Instanz der UIView und fügen Sie die Eigenschaften hinzu

Kurze Antwort :

layer.cornerRadius = 10
layer.borderWidth = 1
layer.borderColor = UIColor.blue.cgColor

Lange Antwort :

Abgerundete Ecken von UIView / UIButton usw.

customUIView.layer.cornerRadius = 10

Randdicke

pcustomUIView.layer.borderWidth = 2

Randfarbe

customUIView.layer.borderColor = UIColor.blue.cgColor
swiftBoy
quelle
Die Frage ist sehr spezifisch und wird im Interface Builder gestellt. Ihre Antwort ist irrelevant.
Shinnyx
-5

Bitte fügen Sie diese 2 einfachen Codezeilen hinzu:

self.YourViewName.layer.cornerRadius = 15
self.YourViewName.layer.masksToBounds = true

Es wird gut funktionieren.

Sneha Patil
quelle