Como definir o cornerRadius apenas para o canto superior esquerdo e superior direito de um UIView?

408

Existe uma maneira de definir cornerRadiusapenas o canto superior esquerdo e superior direito de um UIView?

Eu tentei o seguinte, mas ele acabou não vendo mais a vista.

UIView *view = [[UIView alloc] initWithFrame:frame];

CALayer *layer = [CALayer layer];
UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRoundedRect:frame byRoundingCorners:(UIRectCornerTopLeft|UIRectCornerTopRight) cornerRadii:CGSizeMake(3.0, 3.0)];
layer.shadowPath = shadowPath.CGPath;
view.layer.mask = layer;
tom
fonte
9
Após sua edição, três coisas a serem corrigidas: (1) o caminho arredondado deve ser baseado view.bounds, não frame, (2) a camada deve ser a CAShapeLayer, não CALayer; (3) defina a camada path, não shadowPath.
Kurt Revis
11
Possível duplicata desta pergunta e resposta .
Stuart
Use o algoritmo de curva de Bezier, para criar curvas em um CGPath. Tenho certeza de que faz parte do CoreGraphics. Caso contrário, o site en.wikipedia.org/wiki/Bézier_curve possui ótimas definições e animações.
Nate Symer # 01
Veja minha resposta aqui: stackoverflow.com/a/50396485/6246128
wcarhart

Respostas:

226

Preste atenção ao fato de que, se você tiver restrições de layout associadas, atualize-o da seguinte forma na subclasse UIView:

override func layoutSubviews() {
    super.layoutSubviews()
    roundCorners(corners: [.topLeft, .topRight], radius: 3.0)
}

Se você não fizer isso, não aparecerá.


E para os cantos arredondados, use a extensão:

extension UIView {
   func roundCorners(corners: UIRectCorner, radius: CGFloat) {
        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        layer.mask = mask
    }
}


Caso adicional do controlador de vista : Se você não pode ou não deseja subclassificar uma vista, ainda pode arredondá-la. Faça isso a partir do seu controlador de exibição, substituindo a viewWillLayoutSubviews()função, da seguinte maneira:

class MyVC: UIViewController {
    /// The view to round the top-left and top-right hand corners
    let theView: UIView = {
        let v = UIView(frame: CGRect(x: 10, y: 10, width: 200, height: 200))
        v.backgroundColor = .red
        return v
    }()

    override func loadView() {
        super.loadView()
        view.addSubview(theView)
    }

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()

        // Call the roundCorners() func right there.
        theView.roundCorners(corners: [.topLeft, .topRight], radius: 30)
    }
}
Stéphane de Luca
fonte
3
Não é absolutamente uma resposta, o autor estava perguntando como arredondar cantos específicos, não como sincronizar o raio dos cantos com as alterações de layout.
#
11
Esta é a resposta não faz sentido.
Tiago Couto
11
a resposta foi corrigida recentemente .. @kelin #
Michael
2
isso definitivamente virou a esquina.
precisa saber é o seguinte
Você precisa fazer isso depois que a vista aparecer
Jonathan.
535

Não sei por que sua solução não funcionou, mas o código a seguir está funcionando para mim. Crie uma máscara de bezier e aplique-a à sua visualização. No meu código abaixo, eu estava arredondando os cantos inferiores do _backgroundViewcom um raio de 3 pixels. selfé um costume UITableViewCell:

UIBezierPath *maskPath = [UIBezierPath
    bezierPathWithRoundedRect:self.backgroundImageView.bounds
    byRoundingCorners:(UIRectCornerBottomLeft | UIRectCornerBottomRight)
    cornerRadii:CGSizeMake(20, 20)
];

CAShapeLayer *maskLayer = [CAShapeLayer layer];

maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;

self.backgroundImageView.layer.mask = maskLayer;

Versão Swift com algumas melhorias:

let path = UIBezierPath(roundedRect:viewToRound.bounds, byRoundingCorners:[.TopRight, .BottomLeft], cornerRadii: CGSizeMake(20, 20))
let maskLayer = CAShapeLayer()

maskLayer.path = path.CGPath
viewToRound.layer.mask = maskLayer

Versão Swift 3.0:

let path = UIBezierPath(roundedRect:viewToRound.bounds,
                        byRoundingCorners:[.topRight, .bottomLeft],
                        cornerRadii: CGSize(width: 20, height:  20))

let maskLayer = CAShapeLayer()

maskLayer.path = path.cgPath
viewToRound.layer.mask = maskLayer

Extensão rápida aqui

Yunus Nedim Mehel
fonte
2
tente no campo de texto. sucesso na esquerda, falha na direita
Rainer Liao
10
@RainerLiao eu tive o mesmo problema, fiz tudo isso no viewDidLoadmétodo, movi- lo para viewDidAppeare funcionou.
Lucho
como posso definir isso para funcionar em qualquer dispositivo. isso só funciona bem para o simulatortamanho do storyboard. ex: if the simulator size is 6s it works fine for 6s, but not of others.como posso superar isso.
Chanaka Caldera
11
Pequeno erro de sintaxe na versão Swift 3: path.CGPathdeveria serpath.cgPath
Rob
@RainerLiao se você não quiser que ele apareça conforme a visualização aparece, altere-a para viewWillAppear. Isso também funciona.
Matthew knippen
263

Aqui está uma versão Swift da resposta @JohnnyRockex

extension UIView {

    func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
         let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
         let mask = CAShapeLayer()
         mask.path = path.cgPath
         self.layer.mask = mask
    }

}

view.roundCorners([.topLeft, .bottomRight], radius: 10)

Nota

Se você estiver usando o Layout automático , precisará subclassificar UIViewe chamar roundCornersa visualização layoutSubviewspara obter o efeito ideal.

class View: UIView {
    override func layoutSubviews() {
        super.layoutSubviews()

        self.roundCorners([.topLeft, .bottomLeft], radius: 10)
    }
}
Arbitur
fonte
12
Ótima extensão. No entanto: .TopRighte .BottomRightnão parece funcionar para mim.
Onichan 25/03
4
em Swift 2 :view.roundCorners([.TopLeft , .BottomLeft], radius: 10)
fahrulazmi
2
Não está funcionando do lado direito, porque os limites de sua visualização ainda não estão bem definidos com o layout automático ... Atualmente, estou enfrentando o mesmo problema.
dosdos
3
@dosdos Subclasse que visualiza e no layoutSubviews arredondam os cantos de si.
Arbitur #
10
Se você usa o layout automático e não tem a referência para a exibição que deseja arredondar, pode chamar .layoutIfNeeded()esse método.
Zgjie 18/05
210

E finalmente… existe o CACornerMask no iOS11! Com CACornerMaskisso pode ser feito muito fácil:

let view = UIView()
view.clipsToBounds = true
view.layer.cornerRadius = 10
view.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner] // Top right corner, Top left corner respectively
Sergey Belous
fonte
11
isso definitivamente funciona melhor. sempre tivemos problemas com as outras soluções ao arredondar as bordas das células de tableview com dimensionamento dinâmico.
cornr
2
O projeto deve oferecer suporte ao iOS 11 em diante para usar essa solução.
Aliens
13
@ Aliens e ... eu mencionei isso.
Sergey Belous
11
As outras respostas não funcionam ao girar o dispositivo, esse código funciona para rotação e permite que você rode algumas esquinas; essa deve ser a resposta aceita.
precisa saber é o seguinte
11
Simples é bonito #
eharo2
99

Exemplo de código Swift aqui: https://stackoverflow.com/a/35621736/308315


Não diretamente. Voce terá que:

  1. Crie um CAShapeLayer
  2. Defina pathcomo CGPathRefbaseado, view.boundsmas com apenas dois cantos arredondados (provavelmente usando +[UIBezierPath bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:])
  3. Defina seu view.layer.maskpara ser oCAShapeLayer
Kurt Revis
fonte
21
Esteja avisado isso vai prejudicar o desempenho se você fazê-lo em mais do que apenas um par de pontos de vista ...
jjxtra
@jjxtra Então, qual é a melhor maneira de fazer isso sem muita perda de desempenho? Eu quero mostrá-lo em UITableViewCell.
Xi.lin
@ xi.lin pelo que me lembro de definir layer.shouldRasterize == SIM melhora a velocidade 5 vezes mais ou menos. Mas os documentos dizem que só funciona se você trabalhar com células não transparentes. Experimente.
Codrut # 9/17
64

Aqui está um método curto implementado assim:

- (void)viewDidLoad {
    [super viewDidLoad];
    UIButton *openInMaps = [UIButton new];
    [openInMaps setFrame:CGRectMake(15, 135, 114, 70)];
    openInMaps = (UIButton *)[self roundCornersOnView:openInMaps onTopLeft:NO topRight:NO bottomLeft:YES bottomRight:NO radius:5.0];
}

- (UIView *)roundCornersOnView:(UIView *)view onTopLeft:(BOOL)tl topRight:(BOOL)tr bottomLeft:(BOOL)bl bottomRight:(BOOL)br radius:(float)radius {

    if (tl || tr || bl || br) {
        UIRectCorner corner = 0;
        if (tl) {corner = corner | UIRectCornerTopLeft;}
        if (tr) {corner = corner | UIRectCornerTopRight;}
        if (bl) {corner = corner | UIRectCornerBottomLeft;}
        if (br) {corner = corner | UIRectCornerBottomRight;}

        UIView *roundedView = view;
        UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:roundedView.bounds byRoundingCorners:corner cornerRadii:CGSizeMake(radius, radius)];
        CAShapeLayer *maskLayer = [CAShapeLayer layer];
        maskLayer.frame = roundedView.bounds;
        maskLayer.path = maskPath.CGPath;
        roundedView.layer.mask = maskLayer;
        return roundedView;
    }
    return view;
}
Johnny Rockex
fonte
Que tal definir cores? maskLayer.borderWidth = 10; maskLayer.borderColor = [UIColor redColor] .CGColor; não está funcionando para mim, senhor.
kiran
11
@kiran uma máscara não tem uma cor, você pode adicionar uma segunda CAShapeLayer se você quiser ter uma borda
Johnny Rockex
25

No Swift 4.1 e no Xcode 9.4.1

No iOS 11, essa única linha é suficiente:

detailsSubView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]//Set your view here

Veja o código completo:

//In viewDidLoad
if #available(iOS 11.0, *){
        detailsSubView.clipsToBounds = false
        detailsSubView.layer.cornerRadius = 10
        detailsSubView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
} else {
      //For lower versions
}

Mas para versões inferiores

let rectShape = CAShapeLayer()
    rectShape.bounds = detailsSubView.frame
    rectShape.position = detailsSubView.center
    rectShape.path = UIBezierPath(roundedRect: detailsSubView.bounds,    byRoundingCorners: [.topLeft , .topRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath
    detailsSubView.layer.mask = rectShape

O código completo é.

if #available(iOS 11.0, *){
    detailsSubView.clipsToBounds = false
    detailsSubView.layer.cornerRadius = 10
    detailsSubView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
}else{
    let rectShape = CAShapeLayer()
    rectShape.bounds = detailsSubView.frame
    rectShape.position = detailsSubView.center
    rectShape.path = UIBezierPath(roundedRect: detailsSubView.bounds,    byRoundingCorners: [.topLeft , .topRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath
    detailsSubView.layer.mask = rectShape
}

Se você estiver usando o AutoResizing no storyboard, escreva este código em viewDidLayoutSubviews () .

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if #available(iOS 11.0, *){
        detailsSubView.clipsToBounds = false
        detailsSubView.layer.cornerRadius = 10
        detailsSubView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
    }else{
        let rectShape = CAShapeLayer()
        rectShape.bounds = detailsSubView.frame
        rectShape.position = detailsSubView.center
        rectShape.path = UIBezierPath(roundedRect: detailsSubView.bounds,    byRoundingCorners: [.topLeft , .topRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath
        detailsSubView.layer.mask = rectShape
    }
}
iOS
fonte
11
Não é o trabalho iOS 9, mas funciona com o 11
Ali Ihsan URAL
Alguma solução para o ios 9?
jey
@jay deixe rectShape = CAShapeLayer () rectShape.bounds = detailsSubView.frame rectShape.position = detailsSubView.center rectShape.path = UIBezierPath (roundedRect: detailsSubView.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: cornerRadii 20, height: 20)). CgPath detailsSubView.layer.mask = rectShape Este código pode funcionar no iOS 9
iOS
@ jay verificar se não me informar
iOS
Não está funcionando para o ios 9. Não há borda na parte do canto.
jey
24

iOS 11, Swift 4
E você pode tentar este código:

if #available(iOS 11.0, *) {
   element.clipsToBounds = true
   element.layer.cornerRadius = CORNER_RADIUS
   element.layer.maskedCorners = [.layerMaxXMaxYCorner]
} else {
   // Fallback on earlier versions
}

E você pode usar isso na célula de exibição de tabela.

reza_khalafi
fonte
11
essa é a resposta certa para a codificação de hoje. adeus para mascarar a camada.
Alen Liang
11
Essa deve ser a melhor resposta!
fujianjin6471 3/06/19
18

Esta seria a resposta mais simples:

yourView.layer.cornerRadius = 8
yourView.layer.masksToBounds = true
yourView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
pierre23
fonte
tag que é a solução para iOS 11 ou superior
Ankur Lahiry
16

Experimente este código,

UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:( UIRectCornerTopLeft | UIRectCornerTopRight) cornerRadii:CGSizeMake(5.0, 5.0)];

CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = self.view.bounds;
maskLayer.path  = maskPath.CGPath;

view.layer.mask = maskLayer;

fonte
15

Emma: .TopRighte .BottomRightnão está trabalhando para você, talvez porque a chamada para view.roundCornersé feita ANTES da final view boundsser calculada. Observe que o valor Bezier Pathderiva dos limites da vista no momento em que é chamada. Por exemplo, se o layout automático restringir a vista, os cantos arredondados no lado direito podem estar fora da vista. Tente ligar viewDidLayoutSubviews, onde o limite da visualização é final.

David Barta
fonte
Obrigado. Para mim, o que resolveu o problema foi mover a chamada para a implementação fornecida pelo "Arbitur" de viewDidLoad e viewWillAppear para viewDidAppear. Eu poderia fazer isso, pois meu controle é inicialmente definido como oculto.
Matti
Você está certo. Isso criará problemas com o pagamento automático e você fez um bom trabalho.
Ashish Kakkad
15

Swift 4 Swift 5 maneira fácil em 1 linha

Uso:

//MARK:- Corner Radius of only two side of UIViews
self.roundCorners(view: yourview, corners: [.bottomLeft, .topRight], radius: 12.0)

Função:

//MARK:- Corner Radius of only two side of UIViews
func roundCorners(view :UIView, corners: UIRectCorner, radius: CGFloat){
        let path = UIBezierPath(roundedRect: view.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        view.layer.mask = mask
}

No Objetivo-C

Uso:

[self.verticalSeparatorView roundCorners:UIRectCornerTopLeft radius:10.0];

Função usada em uma categoria (apenas um canto):

-(void)roundCorners: (UIRectCorner) corners radius:(CGFloat)radius {
        UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(radius, radius)];
        CAShapeLayer *mask = [[CAShapeLayer alloc] init];
        mask.path = path.CGPath;
        self.layer.mask = mask;
    }
Shakeel Ahmed
fonte
Apenas lembre-se que os cantos de sua visão não são calculados até o viewDidLayoutSubviews é feito para que você deve chamar roundCorners func dentro dele
Jirson Tavera
você pode dizer como posso adicionar sombra a essas visualizações?
Vadlapalli Masthan
@ ShakeelAhmed, isso não funcionará se você quiser adicionar uma sombra à exibição.
Mojtaba al moussawi 02/07/19
primeiro raio de canto add e depois adicionar sombra
Shakeel Ahmed
10

Minha solução para arredondar cantos específicos do UIView e UITextFiels no swift é usar

.layer.cornerRadius

e

layer.maskedCorners

de UIView ou UITextFields reais.

Exemplo:

fileprivate func inputTextFieldStyle() {
        inputTextField.layer.masksToBounds = true
        inputTextField.layer.borderWidth = 1
        inputTextField.layer.cornerRadius = 25
        inputTextField.layer.maskedCorners = [.layerMaxXMaxYCorner,.layerMaxXMinYCorner]
        inputTextField.layer.borderColor = UIColor.white.cgColor
    }

E usando

.layerMaxXMaxYCorner

e

.layerMaxXMinYCorner

, Posso especificar o canto superior direito e inferior direito do UITextField a ser arredondado.

Você pode ver o resultado aqui:

insira a descrição da imagem aqui

Bane M
fonte
Perfeito para combinação de bordas e cantos específicos 🎉🎉🎉
nomnom 22/01
8

Swift 4

extension UIView {

    func roundTop(radius:CGFloat = 5){
        self.clipsToBounds = true
        self.layer.cornerRadius = radius
        if #available(iOS 11.0, *) {
            self.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner]
        } else {
            // Fallback on earlier versions
        }
    }

    func roundBottom(radius:CGFloat = 5){
        self.clipsToBounds = true
        self.layer.cornerRadius = radius
        if #available(iOS 11.0, *) {
            self.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner]
        } else {
            // Fallback on earlier versions
        }
    }
}
MrMins
fonte
Você salvou meu dia no meu caso eu tive que fazer a exibição de tabela arredondado para células particulares
Shakti
Ans perfeito de acordo com minha exigência. Eu usei toda a resposta, nada funcionou para mim, mas sua resposta me ajudou e resolveu meu problema.
Nikita Patil
6

Uma maneira de fazer isso programaticamente seria criar uma UIViewparte superior da parte UIViewque possui cantos arredondados. Ou você pode esconder o topo por baixo de alguma coisa.

Nate Symer
fonte
6
É uma solução muito feia: P
Arbitur
6
    // Create the path (with only the top-left corner rounded)
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds 
                           byRoundingCorners:(UIRectCornerBottomLeft | UIRectCornerBottomRight) 
                           cornerRadii:CGSizeMake(7.0, 7.0)];

// Create the shape layer and set its path
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = cell.stripBlackImnageView.bounds;
maskLayer.path = maskPath.CGPath; 
// Set the newly created shapelayer as the mask for the image view's layer
view.layer.mask = maskLayer;
Spydy
fonte
4

A maneira mais fácil seria fazer uma máscara com uma camada de canto arredondado.

CALayer *maskLayer = [CALayer layer];
maskLayer.frame = CGRectMake(0,0,maskWidth ,maskHeight);
maskLayer.contents = (__bridge id)[[UIImage imageNamed:@"maskImageWithRoundedCorners.png"] CGImage];

aUIView.layer.mask = maskLayer;

E não se esqueça de:

#import <QuartzCore/QuartzCore.h>
Matt Hudson
fonte
4

Todas as respostas já dadas são realmente boas e válidas (especialmente a idéia de Yunus de usar a maskpropriedade).

No entanto, eu precisava de algo um pouco mais complexo, porque minha camada costumava mudar de tamanho, o que significa que eu precisava chamar essa lógica de mascaramento todas as vezes e isso era um pouco chato.

Usei extensionspropriedades rápidas e computadas para criar uma cornerRadiipropriedade real que cuida da atualização automática da máscara quando a camada é colocada.

Isto foi conseguido usando a grande biblioteca de Aspectos Peter Steinberg para swizzling.

O código completo está aqui:

extension CALayer {
  // This will hold the keys for the runtime property associations
  private struct AssociationKey {
    static var CornerRect:Int8 = 1    // for the UIRectCorner argument
    static var CornerRadius:Int8 = 2  // for the radius argument
  }

  // new computed property on CALayer
  // You send the corners you want to round (ex. [.TopLeft, .BottomLeft])
  // and the radius at which you want the corners to be round
  var cornerRadii:(corners: UIRectCorner, radius:CGFloat) {
    get {
      let number = objc_getAssociatedObject(self, &AssociationKey.CornerRect)  as? NSNumber ?? 0
      let radius = objc_getAssociatedObject(self, &AssociationKey.CornerRadius)  as? NSNumber ?? 0
      return (corners: UIRectCorner(rawValue: number.unsignedLongValue), radius: CGFloat(radius.floatValue))
    }
    set (v) {
      let radius = v.radius
      let closure:((Void)->Void) = {
        let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: v.corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.CGPath
        self.mask = mask
      }
      let block: @convention(block) Void -> Void = closure
      let objectBlock = unsafeBitCast(block, AnyObject.self)
      objc_setAssociatedObject(self, &AssociationKey.CornerRect, NSNumber(unsignedLong: v.corners.rawValue), .OBJC_ASSOCIATION_RETAIN)
      objc_setAssociatedObject(self, &AssociationKey.CornerRadius, NSNumber(float: Float(v.radius)), .OBJC_ASSOCIATION_RETAIN)
      do { try aspect_hookSelector("layoutSublayers", withOptions: .PositionAfter, usingBlock: objectBlock) }
      catch _ { }
    }
  }
}

Eu escrevi um post simples explicando isso.

apouche
fonte
2

É assim que você pode definir um raio de canto para cada canto de um botão com o Xamarin em C # :

var maskPath = UIBezierPath.FromRoundedRect(MyButton.Bounds, UIRectCorner.BottomLeft | UIRectCorner.BottomRight,
    new CGSize(10.0, 10.0));
var maskLayer = new CAShapeLayer
{
    Frame = MyButton.Bounds,
    Path = maskPath.CGPath
};
MyButton.Layer.Mask = maskLayer;
jfmg
fonte
2

Uma extensão adorável para reutilizar a solução Yunus Nedim Mehel

Swift 2.3

extension UIView {
func roundCornersWithLayerMask(cornerRadii: CGFloat, corners: UIRectCorner) {
    let path = UIBezierPath(roundedRect: bounds,
                            byRoundingCorners: corners,
                            cornerRadii: CGSize(width: cornerRadii, height: cornerRadii))
    let maskLayer = CAShapeLayer()
    maskLayer.path = path.CGPath
    layer.mask = maskLayer
} }

Uso

let view = UIView()
view.roundCornersWithLayerMask(10,[.TopLeft,.TopRight])
apinho
fonte
Solução limpa e agradável
Aggressor
1

Depois da alteração do código @apinho No Swift 4.3 funcionando bem

extension UIView {
func roundCornersWithLayerMask(cornerRadii: CGFloat, corners: UIRectCorner) {
    let path = UIBezierPath(roundedRect: bounds,
                            byRoundingCorners: corners,
                            cornerRadii: CGSize(width: cornerRadii, height: cornerRadii))
    let maskLayer = CAShapeLayer()
    maskLayer.path = path.cgPath
    layer.mask = maskLayer
  }
}

Para usar esta função para você visualizar

YourViewName. roundCornersWithLayerMask(cornerRadii: 20,corners: [.topLeft,.topRight])
Sanjay Mishra
fonte
0

Outra versão da resposta de Stephane .

import UIKit

    class RoundCornerView: UIView {
    var corners : UIRectCorner = [.topLeft,.topRight,.bottomLeft,.bottomRight]
        var roundCornerRadius : CGFloat = 0.0
        override func layoutSubviews() {
            super.layoutSubviews()
            if corners.rawValue > 0 && roundCornerRadius > 0.0 {
                self.roundCorners(corners: corners, radius: roundCornerRadius)
            }
        }
        private func roundCorners(corners: UIRectCorner, radius: CGFloat) {
            let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
            let mask = CAShapeLayer()
            mask.path = path.cgPath
            layer.mask = mask
        }

    }
mehdi
fonte
0

No Swift 4.2, crie-o @IBDesignableassim:

@IBDesignable

class DesignableViewCustomCorner: UIView {

    @IBInspectable var cornerRadious: CGFloat = 0 {
        didSet {
            let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: cornerRadious, height: cornerRadious))
            let mask = CAShapeLayer()
            mask.path = path.cgPath
            self.layer.mask = mask
        }
    }

}
Sreeraj VR
fonte
0

Extensão simples

extension UIView {
    func roundCorners(corners: UIRectCorner, radius: CGFloat) {
        if #available(iOS 11, *) {
            self.clipsToBounds = true
            self.layer.cornerRadius = radius
            var masked = CACornerMask()
            if corners.contains(.topLeft) { masked.insert(.layerMinXMinYCorner) }
            if corners.contains(.topRight) { masked.insert(.layerMaxXMinYCorner) }
            if corners.contains(.bottomLeft) { masked.insert(.layerMinXMaxYCorner) }
            if corners.contains(.bottomRight) { masked.insert(.layerMaxXMaxYCorner) }
            self.layer.maskedCorners = masked
        }
        else {
            let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
            let mask = CAShapeLayer()
            mask.path = path.cgPath
            layer.mask = mask
        }
    }
}

Uso:

view.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 12)
FunkyKat
fonte