Dando cantos arredondados ao UIView

577

Minha visualização de login possui uma subview que possui um UIActivityView e um UILabelditado "Conectando ...". Essa subvisão possui cantos que não são arredondados. Como posso fazê-los circular?

Existe alguma maneira de fazer isso dentro do meu xib?

itsaboutcode
fonte
6
Fazer algo como isso em IB exigiria uma imagem pré-renderizados com cantos arredondados
Ed Marty
9
Não necessariamente @ ed-marty, esta resposta de @Gujamin merece mais crédito, pois mostra como aplicar a cornerRadiuspropriedade à tabela usando apenas o Interface Builder, sem precisar usar imagens pré-renderizadas ou defini-las no código.
djskinner

Respostas:

1219

Tente isto

#import <QuartzCore/QuartzCore.h> // not necessary for 10 years now  :)

...

view.layer.cornerRadius = 5;
view.layer.masksToBounds = true;

Nota: Se você estiver tentando aplicar cantos arredondados à UIViewControllervisualização de uma, ela não deve ser aplicada no construtor do controlador de visualização, mas sim -viewDidLoad, após, na viewverdade , é instanciada.

Ed Marty
fonte
6
Observe que a propriedade existe apenas no iPhone 3.0, e não nas versões anteriores.
Kendall Helmstetter Gelner 02/10/09
5
Eu só tenho que dizer que essa foi uma das respostas mais imediatamente satisfatórias que eu já vi no SO. Verificar aqui primeiro me salvou uma hora de luta com um editor de imagens e teria tornado minha visão mais frágil às alterações de cores / dimensionamento. Obrigado!
23610 Justin Searls
20
Nota relacionada: qualquer pessoa interessada em mais itens visuais (ou seja, sombra) para aplicar facilmente a um UIView deve verificar a referência da classe CALayer. A maioria é tão fácil quanto definir um ou dois valores de propriedade, como a resposta acima: developer.apple.com/mac/library/documentation/GraphicsImaging/…
Justin Searls
6
@ Ben Collins (ou qualquer outra pessoa que tenha esse problema), verifique se a sua exibição tem "subviews de clipes" definidos. Você pode verificar isso no construtor de interface.
zem
2
isso funciona muito bem, mas se você tiver muitos desses cantos arredondados em qualquer tipo de exibição ou animação de rolagem (tentei usá-los em um UITableView), seu desempenho sofrerá bastante. Agradável rolagem suave exibição de tabela rapidamente tornar-se instável :(
Slee
261

Você também pode usar o recurso Atributos de Tempo de Execução Definidos pelo Usuário do construtor de interface para definir o caminho da chave layer.cornerRadiuspara um valor. Certifique-se de incluir a QuartzCorebiblioteca.

Esse truque também funciona para definir layer.borderWidth, no entanto, não funcionará, layer.borderColorpois espera-se que CGColornão seja a UIColor.

Você não poderá ver os efeitos no storyboard porque esses parâmetros são avaliados em tempo de execução.

Usando o Construtor de Interface para definir o raio do canto

Gujamin
fonte
10
lembre-se de marcar a Clip Subviewsopção para a visualização IB também #
Peter
2
(ou) adicione um caminho-chave: layer.masksToBounds, Tipo: boolean: Checked
Amitabh
64

Agora você pode usar uma categoria rápida no UIView (código abaixo da imagem) com @IBInspectable para mostrar o resultado no storyboard (se você estiver usando a categoria, use apenas cornerRadius e não layer.cornerRadius como caminho principal.

extension UIView {
    @IBInspectable var cornerRadius: CGFloat {
        get {
            return layer.cornerRadius
        }
        set {
            layer.cornerRadius = newValue
            layer.masksToBounds = newValue > 0
        }
    }
}

insira a descrição da imagem aqui

Guilherme Torres Castro
fonte
E se você estiver usando uma subclasse personalizada, marque-a @IBDesignablepara obter uma visualização ao vivo no IB! (Mais em nshipster.com/ibinspectable-ibdesignable )
clozach
56

Rápido

Resposta curta:

myView.layer.cornerRadius = 8
myView.layer.masksToBounds = true  // optional

Resposta complementar

Se você chegou a esta resposta, provavelmente já viu o suficiente para resolver seu problema. Estou adicionando esta resposta para dar uma explicação visual mais detalhada de por que as coisas fazem o que fazem.

Se você começar com um regular, UIViewele tem cantos quadrados.

let blueView = UIView()
blueView.frame = CGRect(x: 100, y: 100, width: 100, height: 50)
blueView.backgroundColor = UIColor.blueColor()
view.addSubview(blueView)

insira a descrição da imagem aqui

Você pode arredondá-lo alterando a cornerRadiuspropriedade da exibição layer.

blueView.layer.cornerRadius = 8

insira a descrição da imagem aqui

Valores de raio maiores fornecem mais cantos arredondados

blueView.layer.cornerRadius = 25

insira a descrição da imagem aqui

e valores menores fornecem menos cantos arredondados.

blueView.layer.cornerRadius = 3

insira a descrição da imagem aqui

Isso pode ser suficiente para resolver seu problema ali mesmo. No entanto, às vezes uma exibição pode ter uma subvisão ou uma subcamada que fica fora dos limites da exibição. Por exemplo, se eu fosse para adicionar uma sub vista como esta

let mySubView = UIView()
mySubView.frame = CGRect(x: 20, y: 20, width: 100, height: 100)
mySubView.backgroundColor = UIColor.redColor()
blueView.addSubview(mySubView)

ou se eu adicionasse uma sub- camada como esta

let mySubLayer = CALayer()
mySubLayer.frame = CGRect(x: 20, y: 20, width: 100, height: 100)
mySubLayer.backgroundColor = UIColor.redColor().CGColor
blueView.layer.addSublayer(mySubLayer)

Então eu terminaria com

insira a descrição da imagem aqui

Agora, se eu não quiser coisas penduradas fora dos limites, posso fazer isso

blueView.clipsToBounds = true

ou isto

blueView.layer.masksToBounds = true

o que dá esse resultado:

insira a descrição da imagem aqui

Ambos clipsToBoundse masksToBoundssão equivalentes . É apenas que o primeiro é usado com UIViewe o segundo é usado com CALayer.

Veja também

Suragch
fonte
4
Eu também gostaria de acrescentar que definir o raio do canto para metade do lado mais curto (neste caso blueView.frame.size.height/2) resulta em um canto perfeitamente arredondado.
Johann Burgess
44

Uma abordagem diferente da que Ed Marty fez:

#import <QuartzCore/QuartzCore.h>

[v.layer setCornerRadius:25.0f];
[v.layer setMasksToBounds:YES];

Você precisa do setMasksToBounds para carregar todos os objetos do IB ... eu tenho um problema em que minha visão foi arredondada, mas não tinha os objetos do IB: /

isso corrigiu = D espero que ajude!

Kristian Flatheim Jensen
fonte
48
como é diferente? diferente de não usar a sintaxe de ponto?
user102008
3
[v.layer setMasksToBounds: YES]; \ n esta linha é mágica, resolve meu grande problema.
Cullen SUN
3
Eu escrevi isso quando iniciei o desenvolvimento do iOS e não sabia que não havia diferença entre a sintaxe do ponto e a sintaxe do suporte. Por isso, escrevi como "diferente". Meu código também incluía a importação <> que Ed Marty não possuía em sua resposta original (editada posteriormente em) e, portanto, minha resposta ajuda as pessoas a resolver o problema (também conhecido como não importá-lo).
Kristian Flatheim Jensen 08/0315
28

Conforme descrito nesta postagem do blog , aqui está um método para arredondar os cantos de um UIView:

+(void)roundView:(UIView *)view onCorner:(UIRectCorner)rectCorner radius:(float)radius
{
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds
                                                   byRoundingCorners:rectCorner
                                                         cornerRadii:CGSizeMake(radius, radius)];
    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
    maskLayer.frame = view.bounds;
    maskLayer.path = maskPath.CGPath;
    [view.layer setMask:maskLayer];
    [maskLayer release];
}

A parte interessante é que você pode selecionar os cantos que deseja arredondar.

pabloruiz55
fonte
6
Em vez de apenas fornecer um link para um site externo, preferimos que as respostas sejam independentes aqui, então eu trouxe o código relevante da postagem do blog para a sua resposta. As pessoas podem visitar a postagem do blog para obter mais detalhes, mas isso garante que o conteúdo sobreviverá se a postagem em questão desaparecer. Além disso, você postou esta resposta em várias perguntas diferentes que realmente não fizeram a mesma coisa. Essas foram removidas e uma pergunta foi encerrada como duplicada. Gostamos de ter respostas criadas para corresponder a cada pergunta.
Brad Larson
5
Presciente. A postagem do blog é 404 agora.
Anthony C
Essa abordagem é limpa, mas oculta qualquer efeito de sombra na exibição.
Thesummersign
19

Você precisa primeiro importar o arquivo de cabeçalho <QuartzCore/QuartzCore.h>

 #import QuartzCore/QuartzCore.h>

[yourView.layer setCornerRadius:8.0f];
yourView.layer.borderColor = [UIColor redColor].CGColor;
yourView.layer.borderWidth = 2.0f;
[yourView.layer setMasksToBounds:YES];

Não deixe de usar - setMasksToBoundscaso contrário, o efeito pode não ser mostrado.

Samir Jwarchan
fonte
2
Não é necessário importar "QuartzCore / QuartzCore.h"
Sudhir Kumar
Sim, você precisa importar.
quer
3
@LordZsolt Talvez eles tenham mudado isso com o iOS7, mas você não precisa mais importar o QuartzCore.
Marc
14

Você pode usar a seguinte UIViewclasse personalizada, que também pode alterar a cor e a largura da borda. Assim, IBDesignalbevocê também pode alterar os atributos no construtor de interfaces.

insira a descrição da imagem aqui

import UIKit

@IBDesignable public class RoundedView: UIView {

    @IBInspectable var borderColor: UIColor = UIColor.white {
        didSet {
            layer.borderColor = borderColor.cgColor
        }
    }

    @IBInspectable var borderWidth: CGFloat = 2.0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }

    @IBInspectable var cornerRadius: CGFloat = 0.0 {
        didSet {
            layer.cornerRadius = cornerRadius
        }
    }

}
Vakas
fonte
6
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(20, 50, 200, 200)];

view.layer.backgroundColor = [UIColor whiteColor].CGColor;
view.layer.cornerRadius = 20.0;
view.layer.frame = CGRectInset(v.layer.frame, 20, 20);

view.layer.shadowOffset = CGSizeMake(1, 0);
view.layer.shadowColor = [[UIColor blackColor] CGColor];
view.layer.shadowRadius = 5;
view.layer.shadowOpacity = .25;

[self.view addSubview:view];
[view release];
jorik
fonte
A aplicação de setMasksToBounds é importante. Definir uma cor de fundo e sombra projetada não é.
djskinner
3

Swift 4 - Usando o IBDesignable

   @IBDesignable
    class DesignableView: UIView {
    }

    extension UIView
    {

        @IBInspectable
        var cornerRadius: CGFloat {
            get {
                return layer.cornerRadius
            }
            set {
            layer.cornerRadius = newValue
        }
    }
}
Saranjith
fonte
Sinto muito, mas como um iniciante no desenvolvimento do IOS. Como a solução impede layer.cornerRadiusque retorne ao estado original? (ei, como o storyboard do xcode sabe como definir cornerRadiussomente depois que o original UIViewé inicializado)?
23418 AlanSTACK
3
view.layer.cornerRadius = 25
view.layer.masksToBounds = true
Parth Barot
fonte
3

- SwiftUI

No SwiftUI, você pode usar o cornerRadiusmodificador diretamente em qualquer um Viewque desejar. Por exemplo desta pergunta:

Text("Signing In…")
    .padding(16)
    .background(Color.red)
    .cornerRadius(50)

Pré-visualização

Observe que não há mais diamante como raio; portanto, mesmo se você definir o cantoRádio mais da metade da altura , ele arredondará suavemente.

Faça o checkout desta resposta para ver como arredondar cantos específicos no SwiftUI

Mojtaba Hosseini
fonte
2

Por favor, importe, Quartzcore frameworkentão você deve definir setMaskToBoundspara TRUEisso a linha muito importante.

Então: [[yourView layer] setCornerRadius:5.0f];

DeveshM
fonte
2
UIView* viewWithRoundedCornersSize(float cornerRadius,UIView * original)
{
    // Create a white border with defined width
    original.layer.borderColor = [UIColor yellowColor].CGColor;
    original.layer.borderWidth = 1.5;

    // Set image corner radius
    original.layer.cornerRadius =cornerRadius;

    // To enable corners to be "clipped"
    [original setClipsToBounds:YES];
    return original;
}
Ashish Patel
fonte
2

Faça isso programaticamente em obj c

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(20, 50,    200, 200)];

view.layer.backgroundColor = [UIColor whiteColor].CGColor;
view.layer.cornerRadius = 20.0;
view.layer.frame = CGRectInset(v.layer.frame, 20, 20);

[view.layer.shadowOffset = CGSizeMake(1, 0);
view.layer.shadowColor = [[UIColor blackColor] CGColor];
view.layer.shadowRadius = 5;
view.layer.shadowOpacity = .25;][1]

[self.view addSubview:view];

Também podemos fazer isso no stoaryboard.

 layer.cornerRadius  Number  5

insira a descrição da imagem aqui

Vikas Rajput
fonte
2

se o canto redondo não funcionar em viewDidload () , é melhor escrever o código em viewDidLayoutSubview ()

-(void)viewDidLayoutSubviews
{
    viewTextfield.layer.cornerRadius = 10.0 ;                                               
    viewTextfield.layer.borderWidth = 1.0f;
    viewTextfield.layer.masksToBounds =  YES;
    viewTextfield.layer.shadowRadius = 5;
    viewTextfield.layer.shadowOpacity = 0.3;
    viewTextfield.clipsToBounds = NO;
    viewTextfield.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
}

Espero que isto ajude!

Dharmesh Mansata
fonte
0

Você também pode usar uma imagem:

UIImage *maskingImage = [UIImage imageNamed:@"bannerBarBottomMask.png"];
CALayer *maskingLayer = [CALayer layer];
maskingLayer.frame = CGRectMake(-(self.yourView.frame.size.width - self.yourView.frame.size.width) / 2
                                , 0
                                , maskingImage.size.width
                                , maskingImage.size.height);
[maskingLayer setContents:(id)[maskingImage CGImage]];
[self.yourView.layer setMask:maskingLayer];
rico
fonte
0

Propriedade CornerRadious para Round View

set masksToBounds O valor booleano da imagem ainda não será desenhado fora do limite do raio do canto

view.layer.cornerRadius = 5;

view.layer.masksToBounds = YES;
bhautikmewada191
fonte
0

Usando a extensão UIView:

extension UIView {    

func addRoundedCornerToView(targetView : UIView?)
{
    //UIView Corner Radius
    targetView!.layer.cornerRadius = 5.0;
    targetView!.layer.masksToBounds = true

    //UIView Set up boarder
    targetView!.layer.borderColor = UIColor.yellowColor().CGColor;
    targetView!.layer.borderWidth = 3.0;

    //UIView Drop shadow
    targetView!.layer.shadowColor = UIColor.darkGrayColor().CGColor;
    targetView!.layer.shadowOffset = CGSizeMake(2.0, 2.0)
    targetView!.layer.shadowOpacity = 1.0
}
}

Uso:

override func viewWillAppear(animated: Bool) {

sampleView.addRoundedCornerToView(statusBarView)

}
AG
fonte
0

No Swift 4.2 e no Xcode 10.1

let myView = UIView()
myView.frame = CGRect(x: 200, y: 200, width: 200, height: 200)
myView.myViewCorners()
//myView.myViewCorners(width: myView.frame.width)//Pass View width
view.addSubview(myView)

extension UIView {
    //If you want only round corners
    func myViewCorners() {
        layer.cornerRadius = 10
        layer.borderWidth = 1.0
        layer.borderColor = UIColor.red.cgColor
        layer.masksToBounds = true
    }
    //If you want complete round shape, enable above comment line
    func myViewCorners(width:CGFloat) {
        layer.cornerRadius = width/2
        layer.borderWidth = 1.0
        layer.borderColor = UIColor.red.cgColor
        layer.masksToBounds = true
    }
}
iOS
fonte
-4

ON Xcode 6 Sua tentativa

     self.layer.layer.cornerRadius = 5.0f;

ou

    self.layer.layer.cornerRadius = 5.0f;
    self.layer.clipsToBounds = YES;
Saringkhan Vungsin
fonte