É possível definir propriedades de borda do UIView no construtor de interfaces?

184

É possível controlar as propriedades da borda do UIView (cor, espessura, etc ...) diretamente do construtor de interface ou eu posso fazê-lo apenas programaticamente?

matteo.cajani
fonte
Verifique isso http://stackoverflow.com/a/28854514/3177007
Mohamed Jaleel Nazir
1
Caso alguém venha do Google como eu. Para ver essas mudanças refletidas no IB, você só precisa criar uma subclasse do UIView e atribuí-lo a qualquer View que você deseja manipular no IB.
Kanongata

Respostas:

392

Na verdade, você pode definir algumas propriedades da camada de uma visualização por meio do construtor de interfaces. Eu sei que posso definir borderWidth e cornerRadius de uma camada através do xcode. borderColor não funciona, provavelmente porque a camada deseja um CGColor em vez de um UIColor.

Você pode ter que usar Strings em vez de números, mas funciona!

layer.cornerRadius
layer.borderWidth
layer.borderColor

Atualização: layer.masksToBounds = true

exemplo

Atualização: selecione o Tipo apropriado para Keypath:

insira a descrição da imagem aqui

Rich86man
fonte
3
Para você e Peter DeWeese: Eu uso o Xcode 4.6.3 e eu posso definir o tipo de caminho-chave para "Color" sem impleting uma interface CALayer
39
Infelizmente, layer.borderColor não pode ser definido dessa maneira. É um CGColorRef, mas esse tipo de valor IB Color é um UIColor.
Mrgrieves
12
Portanto, é isso que os atributos de tempo de execução definidos pelo usuário fazem! Haha, escrevo para iOS desde 2011 e nunca aprendi para que servem esses campos. Obrigado por esta resposta incrível.
Andy Ibanez
3
Bom, mas você precisa definir o tipo correto para cada propriedade. O tipo para, por exemplo, "layer.cornerRadius" deve ser definido como "Number" em vez de "String"!
Peter Kreinz
5
Além disso, não se esqueça de marcar a caixa de seleção "cortar nos limites" para que o Radius corner funcione.
Pierre-Olivier Simonard
183

A resposta do Rich86Man está correta, mas você pode usar categorias para propriedades de proxy, como layer.borderColor. (Do ConvencionalC 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

Construtor de interface

layer.borderUIColor

O resultado será aparente durante o tempo de execução, não no Xcode.

Editar : você também precisa definir layer.borderWidthpelo menos 1 para ver a borda com a cor escolhida.

No Swift 2.0:

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

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

No Swift 3.0:

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

        get {
            return UIColor(cgColor: self.borderColor!)
        }
    }
}
Peter DeWeese
fonte
Não consigo fazer isso funcionar para mim. O arquivo .m geme por que borderColor precisa ser borderUIColor e corrigi-lo, depois de fazer isso ainda mostra avisos e a cor da borda não é renderizada em tempo de execução. O pouco que é diferente sobre o meu é que tenho @ implementação NameOfFile, não @ implementação CALayer (NameOfFile), eu não entendo a parte CALayer, você poderia explicar que mais, por favor
Dave Haigh
2
@PeterDeWeese grande resposta =)!
c-vilão
1
Você realmente pode usar Number com borderWidth e aceitar um NSNumber. Funciona bem.
Peter DeWeese
1
Esta é definitivamente a melhor solução na minha opinião para resolver o problema do BorderColor. Fantástico uso de categorias!
EricWasTaken
1
Trabalhou em Swift!
KOTIOS
81

Resposta semelhante à do iHulk, mas em Swift

Adicione um arquivo chamado UIView.swift ao seu projeto (ou cole-o em qualquer arquivo):

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

Em seguida, isso estará disponível no Interface Builder para cada botão, imageView, etiqueta etc. no Painel de utilitários> Inspetor de atributos:

Inspetor de atributos

Nota: a borda aparecerá apenas em tempo de execução.

Axel Guilmin
fonte
@Gaurav Que erro você vê? Em qual componente (UIButton, UILabel etc.) você o está usando?
precisa saber é o seguinte
Eu não posso ajudá-lo sem mais detalhes :(
Axel Guilmin 19/04/16
2
Eu estava recebendo falhas do Interface Builder com essa abordagem até ser removido @IBDesignabledo início da extensão.
Albert Bori
1
Isso é incrível ... Obrigado! Estou usando o XCode 8.2.1
bobwki 13/03/19
1
Muito útil e arrumado! Obrigado!
Karl-John Chow
56

Você pode criar uma categoria do UIView e adicioná-lo no arquivo .h da categoria

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

Agora adicione isso no arquivo .m

@dynamic borderColor,borderWidth,cornerRadius;

e isso também em. arquivo 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];
}

agora você verá isso no seu storyboard para todas as subclasses UIView (UILabel, UITextField, UIImageView etc.)

insira a descrição da imagem aqui

É isso. Não é necessário importar a categoria em qualquer lugar, basta adicionar os arquivos da categoria no projeto e ver essas propriedades no storyboard.

iHulk
fonte
2
Complementá-lo com IB_DESIGNABLE fazer IB redesenhar sua exibição personalizada usando o drawRect: método developer.apple.com/library/ios/recipes/...
txulu
3
Isso é ótimo, se você escrever IB_DESIGNABLE no arquivo .h antes da linha de interface, você não precisa adicionar a linha @dynamic em .m
Jasmeet
@ user1618612 não tem nada a ver com a resolução, apenas define as propriedades normais da camada.
IHulk #
11

Para Swift 3 e 4 , se você estiver disposto a usar IBInspectables, existe o seguinte:

@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
fonte
Esta é a melhor solução para mim #
22218
Excelente solução, obrigado u
Ebtehal___ 25/02/19
7

Embora isso possa definir as propriedades, ele não reflete na IB. Portanto, se você está essencialmente escrevendo código no IB, pode fazê-lo no seu código-fonte

Zayin Krige
fonte
1
Bem-vindo ao MVC! Você visualiza propriedades nunca deve estar no código!
Alejandro Iván
2
^ Não é isso que o MVC é.
Andrew Plummer
1
Considerando que 95% do tempo este código vai no controlador, é também MVC, é claro que você deve adequadamente subclasse ou prolongar a sua vista, em seguida, apenas a sua configuração sobre a codificação :-)
Daniele Bernardini
4

Se você quiser economizar tempo, use duas UIViewsem cima da outra, a da parte traseira sendo da cor da borda e a da frente menor, dando o efeito da borda. Também não acho que essa seja uma solução elegante, mas se a Apple se importava um pouco mais, não seria necessário fazer isso.

Matthew Quiros
fonte
10
As soluções alternativas economizam tempo agora e perdem muito mais tempo no futuro.
Lachezar Todorov
0

É absolutamente possível apenas quando você define layer.masksToBounds = truee descansa as coisas.

Sunil Targe
fonte
-1

O storyboard não funciona para mim o tempo todo, mesmo depois de tentar toda a solução aqui

Portanto, é sempre uma resposta perfeita usar o código, basta criar a instância IBOutlet do UIView e adicionar as propriedades

Resposta curta :

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

Resposta longa :

Cantos arredondados de UIView / UIButton etc

customUIView.layer.cornerRadius = 10

Espessura da borda

pcustomUIView.layer.borderWidth = 2

Cor da borda

customUIView.layer.borderColor = UIColor.blue.cgColor
swiftBoy
fonte
A pergunta é muito específica e pergunte como fazê-lo no Interface Builder. Sua resposta é irrelevante.
Shinnyx 24/10/19
-5

Adicione estas 2 linhas simples de código:

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

Vai funcionar bem.

Sneha Patil
fonte