Est-il possible de définir les propriétés de bordure UIView à partir du générateur d'interface?

189

Est-il possible de contrôler les propriétés des bordures UIView (couleur, épaisseur, etc.) directement à partir du constructeur d'interface ou je ne peux le faire que par programme?

matteo.cajani
la source
Vérifiez ceci http://stackoverflow.com/a/28854514/3177007
Mohamed Jaleel Nazir
1
Juste au cas où quelqu'un viendrait de Google comme moi. Pour voir ces changements se refléter dans IB, il vous suffit de créer une sous-classe d'UIView et de l'affecter à la vue que vous souhaitez manipuler dans IB.
Kanongata

Réponses:

393

En fait, vous pouvez définir certaines propriétés de la couche d'une vue via le générateur d'interface. Je sais que je peux définir borderWidth et cornerRadius d'un calque via xcode. borderColor ne fonctionne pas, probablement parce que le calque veut un CGColor au lieu d'un UIColor.

Vous devrez peut-être utiliser des chaînes au lieu de nombres, mais cela fonctionne!

layer.cornerRadius
layer.borderWidth
layer.borderColor

Mise à jour: layer.masksToBounds = true

exemple

Mise à jour: sélectionnez le type approprié pour Keypath:

entrez la description de l'image ici

Rich86man
la source
3
Pour vous et Peter DeWeese: J'utilise Xcode 4.6.3 et je peux définir le type de chemin de clé sur "Couleur" sans implémenter une interface
41
Malheureusement, layer.borderColor ne peut pas être défini de cette façon. C'est un CGColorRef, mais ce type de valeur IB Color est un UIColor.
mrgrieves
12
C'est donc ce que font les attributs d'exécution définis par l'utilisateur! Haha, j'écris pour iOS depuis 2011 et je n'ai jamais appris à quoi servaient ces domaines. Merci pour cette réponse géniale.
Andy Ibanez
3
Bien, mais vous devez définir le type correct pour chaque propriété. Le Type pour par exemple "layer.cornerRadius" doit être réglé sur "Number" au lieu de "String"!
Peter Kreinz
5
N'oubliez pas non plus de cocher la case "Clip to Bounds" pour que le cornerRadius fonctionne.
Pierre-Olivier Simonard
186

La réponse de Rich86Man est correcte, mais vous pouvez utiliser des catégories pour proxy des propriétés telles que layer.borderColor. (À partir du CocoaPod conventionnel )

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

Générateur d'interface

layer.borderUIColor

Le résultat sera apparent pendant l'exécution, pas dans Xcode.

Modifier : vous devez également définir layer.borderWidthau moins 1 pour voir la bordure avec la couleur choisie.

Dans Swift 2.0:

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

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

Dans Swift 3.0:

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

        get {
            return UIColor(cgColor: self.borderColor!)
        }
    }
}
Peter DeWeese
la source
Je ne peux pas faire fonctionner ça pour moi. Le fichier .m gémit sur le fait que borderColor doit être borderUIColor et pour le corriger, après cela, il affiche toujours des avertissements et la couleur de la bordure ne s'affiche pas au moment de l'exécution. Le bit qui est différent sur le mien est que j'ai @ implémentation NameOfFile, pas @ implémentation CALayer (NameOfFile), je ne comprends pas la partie CALayer, pourriez-vous expliquer cela plus s'il vous plaît
Dave Haigh
2
@PeterDeWeese great answer! =)
c-villain
1
Vous pouvez en fait utiliser Number avec borderWidth et accepter un NSNumber. Ça fonctionne bien.
Peter DeWeese
1
C'est certainement la meilleure solution à mon avis pour résoudre le problème de BorderColor. Utilisation fantastique des catégories!
EricWasTaken le
1
A travaillé à Swift!
KOTIOS
84

Réponse similaire à celle d'iHulk, mais dans Swift

Ajoutez un fichier nommé UIView.swift dans votre projet (ou collez-le simplement dans n'importe quel fichier):

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

Ensuite, cela sera disponible dans Interface Builder pour chaque bouton, imageView, étiquette, etc. dans le panneau Utilitaires> Inspecteur d'attributs:

Inspecteur d'attributs

Remarque: la bordure n'apparaîtra qu'au moment de l'exécution.

Axel Guilmin
la source
@Gaurav Quelle erreur voyez-vous? Sur quel composant (UIButton, UILabel, etc.) l'utilisez-vous?
Axel Guilmin
Je ne peux pas vous aider sans plus de détails :(
Axel Guilmin
2
J'avais des plantages d'Interface Builder avec cette approche jusqu'à ce que je supprime @IBDesignabledepuis le début de l'extension.
Albert Bori
1
C'est incroyable ... Merci! J'utilise XCode 8.2.1
bobwki
1
Très pratique et soigné! Merci!
Karl-John Chow
56

Vous pouvez créer une catégorie d'UIView et l'ajouter dans le fichier .h de la catégorie

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

Maintenant, ajoutez ceci dans le fichier .m

@dynamic borderColor,borderWidth,cornerRadius;

et cela aussi dans. m fichier

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

maintenant, vous le verrez dans votre storyboard pour toutes les sous-classes UIView (UILabel, UITextField, UIImageView, etc.)

entrez la description de l'image ici

C'est tout .. Pas besoin d'importer la catégorie n'importe où, ajoutez simplement les fichiers de la catégorie dans le projet et voyez ces propriétés dans le storyboard.

iHulk
la source
2
Complétez-le avec IB_DESIGNABLE pour que IB redessine votre vue personnalisée en utilisant le drawRect: method developer.apple.com/library/ios/recipes/…
txulu
3
C'est génial, si vous écrivez IB_DESIGNABLE dans le fichier .h avant la ligne d'interface, vous n'avez pas besoin d'ajouter la ligne @dynamic dans .m
Jasmeet
@ user1618612 cela n'a rien à voir avec la résolution, c'est juste la définition des propriétés normales du calque.
iHulk
11

Pour Swift 3 et 4 , si vous êtes prêt à utiliser IBInspectables, il y a ceci:

@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
la source
C'est une meilleure solution pour moi
Mục Đồng
Excellente solution, merci
Ebtehal___
7

bien que cela puisse définir les propriétés, il ne se reflète pas réellement dans IB. Donc, si vous écrivez essentiellement du code dans IB, vous pouvez aussi bien le faire dans votre code source

Zayin Krige
la source
1
Bienvenue chez MVC! Vous ne devez jamais afficher les propriétés dans le code!
Alejandro Iván
2
^ Ce n'est pas ce qu'est MVC.
Andrew Plummer
1
Considérant que 95% du temps ce code va dans le contrôleur, c'est aussi MVC, bien sûr si vous sous-classez correctement ou étendez votre vue alors sa juste configuration sur le codage :-)
Daniele Bernardini
4

Si vous voulez gagner du temps, il suffit d'en utiliser deux l'un UIViewssur l'autre, celui à l'arrière étant la couleur de la bordure et celui à l'avant plus petit, donnant l'effet de bordure. Je ne pense pas non plus que ce soit une solution élégante, mais si Apple se souciait un peu plus, vous ne devriez pas avoir à le faire.

MLQ
la source
10
Les solutions de contournement permettent de gagner du temps maintenant et de perdre beaucoup plus de temps à l'avenir.
Lachezar Todorov
0

Ce n'est absolument possible que lorsque vous définissez layer.masksToBounds = trueet que vous vous reposez.

Sunil Targe
la source
-1

Le storyboard ne fonctionne pas pour moi tout le temps même après avoir essayé toutes les solutions ici

La réponse est donc toujours parfaite en utilisant le code, créez simplement une instance IBOutlet de l'UIView et ajoutez les propriétés

Réponse courte :

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

Longue réponse :

Coins arrondis de UIView / UIButton etc.

customUIView.layer.cornerRadius = 10

Épaisseur de la bordure

pcustomUIView.layer.borderWidth = 2

Couleur de la bordure

customUIView.layer.borderColor = UIColor.blue.cgColor
swiftBoy
la source
La question est très spécifique et demande comment le faire depuis l'Interface Builder. Votre réponse est sans importance.
Shinnyx
-5

Veuillez ajouter ces 2 lignes de code simples:

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

Cela fonctionnera très bien.

Sneha Patil
la source