Czy można ustawić właściwości obramowania UIView z konstruktora interfejsu?


184

Czy można kontrolować właściwości obramowania UIView (kolor, grubość itp.) Bezpośrednio z konstruktora interfejsu, czy mogę to zrobić tylko programowo?



1
Na wypadek, gdyby ktoś pochodził z Google tak jak ja. Aby zobaczyć, jak zmiany te odzwierciedlają się w IB, wystarczy utworzyć podklasę UIView i przypisać ją do dowolnego widoku, którym chcesz manipulować w IB.
Kanongata

Odpowiedzi:


392

W rzeczywistości można ustawić niektóre właściwości warstwy widoku za pomocą konstruktora interfejsów. Wiem, że mogę ustawić borderWidth i cornerRadius warstwy poprzez xcode. borderColor nie działa, prawdopodobnie dlatego, że warstwa chce CGColor zamiast UIColor.

Być może będziesz musiał użyć Ciągów zamiast liczb, ale to działa!

layer.cornerRadius
layer.borderWidth
layer.borderColor

Aktualizacja: layer.masksToBounds = true

przykład

Aktualizacja: wybierz odpowiedni typ dla Keypath:

wprowadź opis zdjęcia tutaj


3
Do Ciebie i Petera DeWeese: Używam Xcode 4.6.3 i mogę ustawić typ słowa kluczowej na „Kolor” bez sugerowania interfejsu CALayer

39
Niestety w ten sposób nie można ustawić layer.borderColor. Jest to CGColorRef, ale ten typ wartości IB Color to UIColor.
mrgrieves

12
TO właśnie robi zdefiniowane przez użytkownika atrybuty środowiska wykonawczego! Haha, piszę na iOS od 2011 roku i nigdy nie dowiedziałem się, do czego służą te pola. Dzięki za tę niesamowitą odpowiedź.
Andy Ibanez

3
Fajnie, ale musisz ustawić poprawny typ dla każdej nieruchomości. Typ np. „Layer.cornerRadius” musi być ustawiony na „Number” zamiast „String”!
Peter Kreinz,

5
Nie zapomnij również zaznaczyć pola wyboru „klip do granic”, aby program cornerRadius działał.
Pierre-Olivier Simonard,

183

Odpowiedź Rich86Man jest poprawna, ale możesz użyć kategorii do określenia właściwości proxy, takich jak layer.borderColor. (Z konwencjonalnego 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

Konstruktor interfejsów

layer.borderUIColor

Wynik będzie widoczny podczas działania, a nie w Xcode.

Edycja : Musisz także ustawić layer.borderWidthco najmniej 1, aby zobaczyć ramkę z wybranym kolorem.

W Swift 2.0:

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

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

W Swift 3.0:

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

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

Nie mogę tego zmusić do pracy. Plik .m jęczy, że borderColor musi być borderUIColor i go naprawić, po wykonaniu tej czynności nadal wyświetla ostrzeżenia, a kolor obramowania nie jest renderowany w czasie wykonywania. To, co różni się w moim, to to, że mam @ implementację NameOfFile, a nie @ implementację CALayer (NameOfFile), nie rozumiem części CALayer, czy mógłbyś to wyjaśnić więcej
Dave Haigh,

2
@PeterDeWeese świetna odpowiedź! =)
c-złoczyńca

1
Rzeczywiście możesz użyć Number z borderWidth i zaakceptować NSNumber. To działa dobrze.
Peter DeWeese

1
To zdecydowanie najlepsze rozwiązanie, moim zdaniem, do rozwiązania problemu BorderColor. Fantastyczne wykorzystanie kategorii!
EricWasTaken

1
Pracowałem w Swift!
KOTIOS

81

Podobna odpowiedź do iHulk, ale w Swift

Dodaj plik o nazwie UIView.swift do swojego projektu (lub po prostu wklej go w dowolnym pliku):

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
        }
    }
}

Następnie będzie to dostępne w Konstruktorze interfejsów dla każdego przycisku, imageView, etykiety itp. W panelu Narzędzia> Inspektor atrybutów:

Inspektor atrybutów

Uwaga: ramka pojawi się tylko w czasie wykonywania.


@Gaurav Jaki błąd widzisz? Na jakim komponencie (UIButton, UILabel itp.) Go używasz?
Axel Guilmin

Nie mogę ci pomóc bez dalszych szczegółów :(
Axel Guilmin

2
Dostawałem awarie Konstruktora interfejsów przy takim podejściu, dopóki nie usunąłem go @IBDesignablez początku rozszerzenia.
Albert Bori

1
To niesamowite ... Dzięki! Używam XCode 8.2.1
bobwki

1
Bardzo przydatny i schludny! Dzięki!
Karl-John Chow

56

Możesz utworzyć kategorię UIView i dodać ją do pliku .h kategorii

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

Teraz dodaj to do pliku .m

@dynamic borderColor,borderWidth,cornerRadius;

i to również w. plik m

-(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];
}

teraz zobaczysz to w swojej serii ujęć dla wszystkich podklas UIView (UILabel, UITextField, UIImageView itp.)

wprowadź opis zdjęcia tutaj

To wszystko .. Nie trzeba importować kategorii w dowolnym miejscu, wystarczy dodać pliki kategorii w projekcie i zobaczyć te właściwości w serii ujęć.


2
Uzupełnij go o IB_DESIGNABLE, aby IB przerysował swój niestandardowy widok za pomocą drawRect: method developer.apple.com/library/ios/recipes/…
txulu

3
To świetnie, jeśli napiszesz IB_DESIGNABLE w pliku .h przed linią interfejsu, nie musisz dodawać linii @dynamicznej w .m
Jasmeet

@ user1618612 nie ma to nic wspólnego z rozdzielczością, po prostu ustawia normalne właściwości warstwy.
iHulk,

11

W przypadku Swift 3 i 4 , jeśli chcesz użyć IBInspectables, jest to:

@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
        }
    }
}

To dla mnie najlepsze rozwiązanie
Mục Đồng

Świetne rozwiązanie, dziękuję
Ebtehal___

7

chociaż może to ustawić właściwości, w rzeczywistości nie odzwierciedla się w IB. Więc jeśli zasadniczo piszesz kod w IB, równie dobrze możesz to zrobić w kodzie źródłowym


1
Witamy w MVC! Wyświetlane właściwości nigdy nie powinny być w kodzie!
Alejandro Iván

2
^ To nie jest MVC.
Andrew Plummer

1
Biorąc pod uwagę, że 95% czasu ten kod trafia do kontrolera, jest to również MVC, oczywiście, jeśli powinieneś właściwie podklasować lub rozszerzyć swój widok, to jego zwykła konfiguracja zamiast kodowania :-)
Daniele Bernardini

4

Jeśli chcesz zaoszczędzić czas, po prostu użyj dwóch UIViewsna sobie, jeden z tyłu ma kolor obramowania, a ten z przodu mniejszy, co daje efekt graniczny. Nie wydaje mi się, żeby było to również eleganckie rozwiązanie, ale jeśli Apple trochę bardziej to obchodzi, nie powinieneś tego robić.


10
Obejścia pozwalają zaoszczędzić czas i marnować znacznie więcej czasu w przyszłości.
Lachezar Todorov

0

Jest to absolutnie możliwe tylko wtedy, gdy ustawiasz layer.masksToBounds = truei odpoczywasz.


-1

Storyboard nie działa dla mnie przez cały czas, nawet po wypróbowaniu wszystkich rozwiązań tutaj

Tak więc zawsze jest idealna odpowiedź przy użyciu kodu, wystarczy utworzyć instancję IBOutlet UIView i dodać właściwości

Krótka odpowiedź :

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

Długa odpowiedź :

Zaokrąglone rogi UIView / UIButton itp

customUIView.layer.cornerRadius = 10

Grubość granicy

pcustomUIView.layer.borderWidth = 2

Kolor ramki

customUIView.layer.borderColor = UIColor.blue.cgColor

Pytanie jest bardzo szczegółowe i zapytaj, jak to zrobić w Konstruktorze interfejsów. Twoja odpowiedź jest nieistotna.
Shinnyx

-5

Dodaj 2 proste linie kodu:

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

Będzie dobrze działać.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.