Cocoa Touch: Como alterar a cor e a espessura da borda do UIView?

Respostas:

596

Você precisa usar a camada da vista para definir a propriedade da borda. por exemplo:

#import <QuartzCore/QuartzCore.h>
...
view.layer.borderColor = [UIColor redColor].CGColor;
view.layer.borderWidth = 3.0f;

Você também precisa vincular ao QuartzCore.framework para acessar esta funcionalidade.

Vladimir
fonte
Existe alguma maneira de definir diferentes larguras / cores para cada lado?
lluismontero
2
@lluismontero I medo que você terá que fazer UIView personalizado com drawRect: método para que
Vladimir
1
Se eu fizer isso e, além disso, tiver uma animação, como um UINavigationController modal descartado, vejo muitas falhas acontecendo, é difícil de descrever. Se eu desativar as bordas, tudo volta ao normal.
Nicu Surdu
5
Apenas um alerta para os outros. O Xcode sugere conectar o UIColor ao CGColorRef como __bridge CGColorRef. Isso não funciona. Precisa ser [UIColor blackColor].CGColorcomo mencionado na resposta.
21814 GoodSp33d
6
#import <QuartzCore/QuartzCore.h>não é mais necessário.
significado-importa
43

Atualização do Xcode 6

Desde a versão mais recente do Xcode, existe uma solução melhor para isso:

Com @IBInspectablevocê pode definir atributos diretamente de dentro do Attributes Inspector.

Meu modo de exibição personalizado @IBInspectable Attributes

Isso define User Defined Runtime Attributespara você:

insira a descrição da imagem aqui

Existem duas abordagens para configurar isso:

Opção 1 (com atualização ao vivo no Storyboard)

  1. Crie MyCustomView.
  2. Isso herda de UIView.
  3. Set @IBDesignable(isso ativa a atualização do View). *
  4. Defina seus Atributos de tempo de execução (borda, etc.) com @IBInspectable
  5. Altere sua classe Views para MyCustomView
  6. Edite no painel de atributos e veja as alterações no Storyboard :)

`

@IBDesignable
class MyCustomView: UIView {
    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = cornerRadius > 0
        }
    }
    @IBInspectable var borderWidth: CGFloat = 0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }
    @IBInspectable var borderColor: UIColor? {
        didSet {
            layer.borderColor = borderColor?.CGColor
        }
    }
}

* @IBDesignablesó funciona quando definido no início doclass MyCustomView

Opção 2 (não funciona desde o Swift 1.2, ver comentários)

Estenda sua classe UIView:

extension UIView {
    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = cornerRadius > 0
        }
    }
    @IBInspectable var borderWidth: CGFloat = 0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }
    @IBInspectable var borderColor: UIColor? {
        didSet {
            layer.borderColor = borderColor?.CGColor
        }
    }
}

Dessa forma, sua visualização padrão sempre possui esses campos editáveis ​​extras Attributes Inspector. Outra vantagem é que você não precisa mudar de classe MycustomViewsempre. No entanto, uma desvantagem disso é que você só verá suas alterações quando executar o aplicativo.

MMachinegun
fonte
1
Sua extensão não funciona na versão mais recente do Xcode a partir de hoje.
Edgar Aroutiounian
1
Vou confirmar @EdgarAroutiounian só para dizer que em Swift 1.2 a segunda abordagem não funciona mais
Sergey Grischyov
E o Objective-C?
Nik Kov
Confira a resposta de spencery2 mais adiante, ele teve tempo para escrevê-lo em Objective-C:
MMachinegun
atualize a extensão para não armazenar um valor e use set (value) {} e faça com que {} acesse a camada diretamente, ela funciona então.
LightningStryk
17

Você também pode criar uma borda com a cor do seu desejo.

view.layer.borderColor = [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1.0].CGColor;

* r, g, b são os valores entre 0 e 255.

rohan-patel
fonte
6
É interessante notar que r, ge bprovavelmente deve ser flutuadores; os divisores também deve ser floats: r / 255.0.
não, a sintaxe C não é como você diz. r, g e b podem ser int, pois as promoções C (e objC IS C) lançam int r = 128 para dobrar ao criar: r / 255.0. A propósito, você conseguiu o dobro e Clang será escalado para o CGFloat.
ingconti
10

Adicione a seguinte extensão @IBInspectables na UIView

extension UIView {

  @IBInspectable var borderWidth: CGFloat {
    get {
      return layer.borderWidth
    }
    set(newValue) {
      layer.borderWidth = newValue
    }
  }

  @IBInspectable var borderColor: UIColor? {
    get {
      if let color = layer.borderColor {
        return UIColor(CGColor: color)
      }
      return nil
    }
    set(newValue) {
      layer.borderColor = newValue?.CGColor
    }
  }
}

E você poderá definir os atributos borderColor e borderWidth diretamente do inspetor de Atributos. Ver imagem em anexo

Inspetor de atributos

Bikramjit Singh
fonte
8

Quando uso a solução CALayer de Vladimir e, no topo da tela, tenho uma animação, como um UINavigationController modal descartando, vejo muitas falhas acontecendo e tendo problemas de desempenho de desenho.

Portanto, outra maneira de conseguir isso, mas sem as falhas e a perda de desempenho, é criar um UIView personalizado e implementar a drawRectmensagem da seguinte maneira:

- (void)drawRect:(CGRect)rect
{
    CGContextRef contextRef = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(contextRef, 1);
    CGContextSetRGBStrokeColor(contextRef, 255.0, 255.0, 255.0, 1.0);
    CGContextStrokeRect(contextRef, rect);    
}
Nicu Surdu
fonte
@ Krish Você armazena a cor em uma variável e, quando precisar alterar a cor da borda, altera o valor da variável e acessa setNeedsDisplaya exibição. Isso forçará o redesenho do UIView e implicitamente será chamado novamente drawRect. Não testado, tho ...
Nicu Surdu
8
view.layer.borderWidth = 1.0
view.layer.borderColor = UIColor.lightGray.cgColor
shaiju mathew
fonte
1
Eu realmente não gosto de pessoas votadas sem uma explicação. Não ajuda ninguém.
precisa
7

Tente este código:

view.layer.borderColor =  [UIColor redColor].CGColor;
view.layer.borderWidth= 2.0;
[view setClipsToBounds:YES];
Vikram Biwal
fonte
4

Eu não sugeriria substituir o drawRect devido a causar um impacto no desempenho.

Em vez disso, eu modificaria as propriedades da classe como abaixo (na sua visualização personalizada):

  - (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
      self.layer.borderWidth = 2.f;
      self.layer.borderColor = [UIColor redColor].CGColor;
    }
  return self;

Não vi nenhuma falha ao adotar a abordagem acima - não sei por que colocar o initWithFrame os interrompe ;-)

DEzra
fonte
3

Eu queria adicionar isso à resposta de @ marczking ( opção 1 ) como um comentário, mas meu status humilde no StackOverflow está impedindo isso.

Eu fiz um porto da resposta de @ marczking para o Objetivo C. Funciona como charme, obrigado @marczking!

UIView + Border.h:

#import <UIKit/UIKit.h>

IB_DESIGNABLE
@interface UIView (Border)

-(void)setBorderColor:(UIColor *)color;
-(void)setBorderWidth:(CGFloat)width;
-(void)setCornerRadius:(CGFloat)radius;

@end

UIView + Border.m:

#import "UIView+Border.h"

@implementation UIView (Border)
// Note: cannot use synthesize in a Category

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

-(void)setBorderWidth:(CGFloat)width
{
    self.layer.borderWidth = width;
}

-(void)setCornerRadius:(CGFloat)radius
{
    self.layer.cornerRadius = radius;
    self.layer.masksToBounds = radius > 0;
}

@end
spencery2
fonte
2

O @IBInspectable está funcionando para mim no iOS 9, Swift 2.0

extension UIView {

@IBInspectable var borderWidth: CGFloat {
get {
        return layer.borderWidth
    }
    set(newValue) {
        layer.borderWidth = newValue
    }
}

@IBInspectable var cornerRadius: CGFloat {
    get {
        return layer.cornerRadius
    }
    set(newValue) {
        layer.cornerRadius = newValue
    }
}

@IBInspectable var borderColor: UIColor? {
    get {
        if let color = layer.borderColor {
            return UIColor(CGColor: color)
        }
        return nil
    }
    set(newValue) {
        layer.borderColor = newValue?.CGColor
    }
}
anhtran
fonte
1

Se você não quiser editar a camada de um UIView, sempre poderá incorporar a vista em outra. A visualização principal teria sua cor de fundo definida para a cor da borda. Também seria um pouco maior, dependendo da largura que você deseja que a borda tenha.

Obviamente, isso só funciona se sua visualização não for transparente e você desejar apenas uma única cor de borda. O OP queria a fronteira na própria visualização, mas essa pode ser uma alternativa viável.

Matt Becker
fonte
0

Se você deseja adicionar bordas diferentes em lados diferentes, pode ser uma subvisão com o estilo específico, é uma maneira fácil de criar.

Yuanfei Zhu
fonte
0

cor da borda do item no veloz 4.2:

let cell = tableView.dequeueReusableCell(withIdentifier: "Cell_lastOrderId") as! Cell_lastOrder
cell.layer.borderWidth = 1
cell.layer.borderColor = UIColor.white.cgColor
cell.layer.cornerRadius = 10
Akhrua
fonte