¿Cómo configurar cornerRadius solo para la esquina superior izquierda y superior derecha de una UIView?

408

¿Hay alguna manera de establecer cornerRadius solo la esquina superior izquierda y superior derecha de a UIView?

Intenté lo siguiente, pero terminó sin ver más la 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
fuente
99
Después de su edición, hay tres cosas que corregir: (1) la ruta redondeada debe basarse en view.bounds, no frame, (2) la capa debe ser a CAShapeLayer, no CALayer; (3) establecer la capa path, no shadowPath.
Kurt Revis
1
Posible duplicado de esta pregunta y respuesta .
Stuart
Use el algoritmo de curva de Bezier para crear curvas en un CGPath. Estoy bastante seguro de que es parte de CoreGraphics. Si no, en.wikipedia.org/wiki/Bézier_curve tiene algunas excelentes definiciones y animaciones.
Nate Symer el
Vea mi respuesta aquí: stackoverflow.com/a/50396485/6246128
wcarhart

Respuestas:

226

Preste atención al hecho de que si tiene restricciones de diseño adjuntas, debe actualizar esto de la siguiente manera en su subclase UIView:

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

Si no haces eso, no aparecerá.


Y para redondear esquinas, use la extensión:

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 de controlador de vista adicional : si no puede o no desea subclasificar una vista, aún puede redondear una vista. Hágalo desde su controlador de vista anulando la viewWillLayoutSubviews()función, de la siguiente manera:

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
fuente
3
No es una respuesta, el autor preguntaba cómo redondear esquinas particulares, no cómo sincronizar el radio de la esquina con los cambios de diseño.
kelin
1
Esta es la respuesta no tiene sentido.
Tiago Couto
1
la respuesta se ha solucionado recientemente .. @kelin
Michael
2
Esto definitivamente dobló la esquina.
aznelite89
Tienes que hacer esto después de que aparezca la vista
Jonathan.
535

No estoy seguro de por qué su solución no funcionó, pero el siguiente código me funciona. Crea una máscara bezier y aplícala a tu vista. En mi código a continuación, estaba redondeando las esquinas inferiores de la _backgroundViewcon un radio de 3 píxeles. selfes una costumbre 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;

Versión rápida con algunas mejoras:

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

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

Versión 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

Extensión rápida aquí

Yunus Nedim Mehel
fuente
2
intente en el campo de texto. éxito en la izquierda, fracaso en la derecha
Rainer Liao
10
@RainerLiao Tuve el mismo problema, hice todo esto en el viewDidLoadmétodo, lo moví viewDidAppeary funcionó.
Lucho
¿Cómo puedo configurar esto para que funcione para cualquier dispositivo? esto solo funciona bien para el simulatortamaño en el guión gráfico. ex: if the simulator size is 6s it works fine for 6s, but not of others.¿Cómo puedo superar esto?
Chanaka Caldera
1
Pequeño error de sintaxis en la versión Swift 3: path.CGPathdebería serpath.cgPath
Rob
@RainerLiao si no desea que se desplace cuando aparezca la vista, cámbielo a su viewWillAppearlugar. Esto tambien funciona.
Matthew Knippen
263

Aquí es un Swift versión de respuesta @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

Si está utilizando Diseño automático , deberá subclasificar su UIViewy llamar roundCornersa la vista layoutSubviewspara obtener un efecto óptimo.

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

        self.roundCorners([.topLeft, .bottomLeft], radius: 10)
    }
}
Arbitur
fuente
12
Gran extensión Sin embargo: .TopRighty .BottomRightno parece funcionar para mí.
Onichan
44
en Swift 2 :view.roundCorners([.TopLeft , .BottomLeft], radius: 10)
fahrulazmi
2
No funciona a la derecha, porque los límites de su vista aún no están bien definidos con autolayout ... Actualmente estoy enfrentando el mismo problema.
dosdos
3
@dosdos Subclase que ve y en diseño Las subvistas redondean las esquinas de uno mismo.
Arbitur
10
Si utiliza el diseño automático y no desea redondear la referencia a la vista, puede llamar a .layoutIfNeeded()este método.
zgjie
210

Y finalmente ... ¡hay CACornerMask en iOS11! Con CACornerMaskesto se puede hacer bastante 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
fuente
1
Esto definitivamente funciona mejor. Siempre tuvimos problemas con las otras soluciones al redondear los bordes de las celdas de vista de tabla de tamaño dinámico.
cornr
2
El proyecto debe ser compatible con iOS 11 en adelante para usar esa solución.
Extranjeros
13
@Aliens y ... mencioné eso.
Sergey Belous
1
Las otras respuestas no funcionan al rotar el dispositivo, este código funciona para la rotación y le permite redondear ciertas esquinas, esta debería ser la respuesta aceptada.
Cloud9999Strife
1
Simple is beautiful
eharo2
99

Ejemplo de código Swift aquí: https://stackoverflow.com/a/35621736/308315


No directamente. Tendras que:

  1. Crear un CAShapeLayer
  2. Establezca pathque esté CGPathRefbasado en view.boundspero con solo dos esquinas redondeadas (probablemente usando+[UIBezierPath bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:] )
  3. Configura tu view.layer.maskpara ser elCAShapeLayer
Kurt Revis
fuente
21
Se advirtió esto perjudicará el rendimiento si lo haces en algo más que un par de puntos de vista ...
jjxtra
@jjxtra Entonces, ¿cuál es la mejor manera de hacerlo sin mucha pérdida de rendimiento? Quiero mostrarlo en UITableViewCell.
xi.lin
@ xi.lin de lo que recuerdo haber configurado layer.shouldRasterize == YES mejora la velocidad 5 veces más o menos. Pero los documentos dicen que solo funciona si trabajas con celdas no transparentes. Dale un tiro.
codrut
64

Aquí hay un método corto implementado así:

- (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
fuente
¿Qué pasa con el color de configuración? maskLayer.borderWidth = 10; maskLayer.borderColor = [UIColor redColor] .CGColor; no está funcionando para mí señor.
kiran
1
@kiran una máscara no tiene color, puedes agregar un segundo CAShapeLayer si quieres tener un borde
Johnny Rockex
25

En swift 4.1 y Xcode 9.4.1

En iOS 11 esta sola línea es suficiente:

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

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

Pero para versiones 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

El código completo es

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
}

Si está utilizando AutoResizing en storyboard, escriba este código en 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
fuente
1
No funciona iOS 9 pero funciona en 11
Ali Ihsan URAL
¿Alguna solución para ios 9?
jey
@jay let rectShape = CAShapeLayer () rectShape.bounds = detailsSubView.frame rectShape.position = detailsSubView.center rectShape.path = UIBezierPath (roundedRect: detailsSubView.bounds, byRoundingCorners: [.topLeft, .topRight]: Corner (CG): cornerRight]: esquina de ancho: CG) 20, altura: 20)). CgPath detailsSubView.layer.mask = rectShape Este código puede funcionar para iOS 9
iOS
@jay comprueba si no me informas
iOS
No funciona para iOS 9. No hay borde en la esquina.
jey
24

iOS 11, Swift 4
Y puedes probar 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
}

Y puede usar esto en la celda de vista de tabla.

reza_khalafi
fuente
1
esa es la respuesta correcta para la codificación de hoy. adiós a la capa de máscara.
Alen Liang
1
¡Esta debe ser la mejor respuesta!
fujianjin6471
18

Esta sería la respuesta más simple:

yourView.layer.cornerRadius = 8
yourView.layer.masksToBounds = true
yourView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
pierre23
fuente
etiqueta que es la solución para iOS 11 o superior
Ankur Lahiry
16

Prueba 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;

fuente
15

Emma: .TopRighty .BottomRightno estoy trabajando para ti tal vez porque la llamada view.roundCornersse realiza ANTES de que view boundsse calculen los finales Tenga en cuenta que Bezier Pathderiva de los límites de la vista en el momento en que se llama. Por ejemplo, si el diseño automático reducirá la vista, las esquinas redondeadas en el lado derecho podrían estar fuera de la vista. Intente llamarlo viewDidLayoutSubviews, donde el límite de la vista es final.

David Barta
fuente
Gracias. Para mí, lo que resolvió el problema fue mover la llamada a la implementación dada por "Arbitur" de viewDidLoad y viewWillAppear para verDidAppear. Podría hacerlo ya que mi control está inicialmente configurado en oculto.
Matti
Tienes razón. Creará un problema con la distribución automática y ha hecho un buen trabajo.
Ashish Kakkad
15

Swift 4 Swift 5 manera fácil en 1 línea

Uso:

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

Función:

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

En el objetivo-C

Uso:

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

Función utilizada en una categoría (solo una esquina):

-(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
fuente
Solo recuerde que las esquinas de su vista no se calculan hasta que viewDidLayoutSubviews esté terminado, por lo que debe llamar a la función roundCorners en su interior
Jirson Tavera
¿Puedes decir cómo puedo agregar sombra a estas vistas?
Vadlapalli Masthan
@ShakeelAhmed esto no funcionará si desea agregar una sombra a la vista.
mojtaba al moussawi
primero agregue el radio de la esquina y luego agregue sombra
Shakeel Ahmed
10

Mi solución para redondear esquinas específicas de UIView y UITextFiels en Swift es usar

.layer.cornerRadius

y

layer.maskedCorners

de UIView real o UITextFields.

Ejemplo:

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
    }

Y al usar

.layerMaxXMaxYCorner

y

.layerMaxXMinYCorner

, Puedo especificar la esquina superior derecha e inferior derecha del UITextField para redondear.

Puedes ver el resultado aquí:

ingrese la descripción de la imagen aquí

Bane M
fuente
Perfecto para la combinación de bordes y esquinas específicas 🎉🎉🎉
nomnom
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
fuente
Me salvaste el día en mi caso. Tenía que hacer que la vista de tabla se redondeara para celdas particulares
Shakti,
Perfecto y de acuerdo a mi requerimiento. Usé toda la respuesta, nada funcionó para mí, pero su respuesta me ayudó y resolvió mi problema.
Nikita Patil
6

Una forma de hacer esto mediante programación sería crear una UIViewparte superior de la UIViewque tenga las esquinas redondeadas. O podrías esconder la parte superior debajo de algo.

Nate Symer
fuente
66
Es una solución muy fea: 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;
Espía
fuente
4

La forma más fácil sería hacer una máscara con una capa de esquina redondeada.

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

aUIView.layer.mask = maskLayer;

Y no olvides:

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

Todas las respuestas ya dadas son realmente buenas y válidas (especialmente la idea de Yunus de usar la maskpropiedad).

Sin embargo, necesitaba algo un poco más complejo porque mi capa a menudo podía cambiar de tamaño, lo que significaba que necesitaba llamar a esa lógica de enmascaramiento cada vez y esto era un poco molesto.

extensionsUsé propiedades rápidas y calculadas para construir un verdaderocornerRadii propiedad que se encarga de actualizar automáticamente la máscara cuando se diseña la capa.

Esto se logró usando Peter Steinberg Great Aspects biblioteca para swizzling.

El código completo está aquí:

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

Escribí una simple publicación de blog explicando esto.

apouche
fuente
2

Así es como puede establecer un radio de esquina para cada esquina de un botón con Xamarin en 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
fuente
2

Una hermosa extensión para reutilizar la solución de 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
fuente
Buena solución limpia
Agresor
1

Después de cambiar el bit de código @apinho En swift 4.3 funciona bien

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 función para ver

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

Otra versión de la respuesta 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
fuente
0

En Swift 4.2, créalo de @IBDesignableesta manera:

@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
fuente
0

Extensión simple

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
fuente