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?



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


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

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.


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


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

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


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.


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.


-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

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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.