Comment définir cornerRadius pour seulement le coin supérieur gauche et supérieur droit d'un UIView?

408

Existe-t-il un moyen de définir cornerRadiusuniquement le coin supérieur gauche et le coin supérieur droit d'un UIView?

J'ai essayé ce qui suit, mais il finit par ne plus voir la vue.

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;
à M
la source
9
Après votre modification, trois choses à corriger: (1) le chemin arrondi doit être basé sur view.bounds, non frame, (2) le calque doit être un CAShapeLayer, non CALayer; (3) définissez le calque path, non shadowPath.
Kurt Revis
1
Copie possible de cette question et réponse .
Stuart
Utilisez l'algorithme de courbe de Bézier pour créer des courbes sur un CGPath. Je suis sûr que cela fait partie de CoreGraphics. Sinon, en.wikipedia.org/wiki/Bézier_curve a de bonnes définitions et animations.
Nate Symer
Voir ma réponse ici: stackoverflow.com/a/50396485/6246128
wcarhart

Réponses:

226

Faites attention au fait que si vous avez des contraintes de mise en page, vous devez l'actualiser comme suit dans votre sous-classe UIView:

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

Si vous ne le faites pas, cela n'apparaîtra pas.


Et pour arrondir les coins, utilisez l'extension:

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


Cas de contrôleur de vue supplémentaire : Que vous ne puissiez pas ou ne souhaitiez pas sous-classer une vue, vous pouvez toujours arrondir une vue. Faites-le à partir de son contrôleur de vue en remplaçant la viewWillLayoutSubviews()fonction, comme suit:

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
la source
3
Ce n'est absolument pas une réponse, l'auteur demandait comment arrondir des coins particuliers, pas comment synchroniser le rayon des coins avec les changements de disposition.
kelin
1
Cette réponse n'a pas de sens.
Tiago Couto
1
la réponse a été corrigée récemment .. @kelin
Michael
2
cela a définitivement tourné le coin.
aznelite89
Vous devez le faire après que la vue soit apparue
Jonathan.
535

Je ne sais pas pourquoi votre solution n'a pas fonctionné mais le code suivant fonctionne pour moi. Créez un masque de Bézier et appliquez-le à votre vue. Dans mon code ci-dessous, j'arrondissais les coins inférieurs de la _backgroundViewavec un rayon de 3 pixels. selfest une coutume 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;

Version Swift avec quelques améliorations:

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

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

Version 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

Extension rapide ici

Yunus Nedim Mehel
la source
2
essayez dans textfield. succès à gauche, échec à droite
Rainer Liao
10
@RainerLiao j'ai eu le même problème, j'ai fait tout cela sur la viewDidLoadméthode, déplacez-le viewDidAppearet cela a fonctionné.
Lucho
comment puis-je configurer cela pour fonctionner sur n'importe quel appareil. cela ne fonctionne que pour la simulatortaille du storyboard. ex: if the simulator size is 6s it works fine for 6s, but not of others.comment puis-je surmonter cela.
Chanaka Caldera
1
Petite erreur de syntaxe dans la version Swift 3: path.CGPathdevrait l'êtrepath.cgPath
Rob
@RainerLiao si vous ne voulez pas qu'il scintille lorsque la vue apparaît, remplacez-le par à la viewWillAppearplace. Cela fonctionne également.
Matthew Knippen
263

Voici une version Swift de la réponse @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)

Remarque

Si vous utilisez la disposition automatique , vous devrez sous-classer votre UIViewet appeler roundCornersla vue layoutSubviewspour un effet optimal.

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

        self.roundCorners([.topLeft, .bottomLeft], radius: 10)
    }
}
Arbitur
la source
12
Grande extension. Cependant: .TopRightet .BottomRightne semblent pas fonctionner pour moi.
2015
4
sur Swift 2 :view.roundCorners([.TopLeft , .BottomLeft], radius: 10)
fahrulazmi
2
Cela ne fonctionne pas à droite, car les limites de votre vue ne sont pas encore bien définies avec la mise en page automatique ... Je suis actuellement confronté au même problème.
dosdos du
3
@dosdos Sous-classe qui affiche et dans layoutSubviews aux coins de soi.
Arbitur
10
Si vous utilisez la disposition automatique et que vous n'avez pas la référence à la vue que vous souhaitez arrondir, vous pouvez appeler .layoutIfNeeded()cette méthode.
zgjie
210

Et enfin… il y a CACornerMask dans iOS11! Avec CACornerMaskcela peut être fait assez facile:

let view = UIView()
view.clipsToBounds = true
view.layer.cornerRadius = 10
view.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner] // Top right corner, Top left corner respectively
Sergey Belous
la source
1
cela fonctionne certainement mieux. nous avons toujours eu des problèmes avec les autres solutions lors de l'arrondi des bords des cellules de dimensionnement dynamique de table.
cornr
2
Le projet doit prendre en charge iOS 11 pour pouvoir utiliser cette solution.
Aliens
13
@Aliens et… je l'ai mentionné.
Sergey Belous
1
Les autres réponses ne fonctionnent pas lors de la rotation de l'appareil, ce code fonctionne pour la rotation et vous permet de contourner certains coins, cela devrait être la réponse acceptée.
Cloud9999Strife
1
Simple is beautiful
eharo2
99

Exemple de code Swift ici: https://stackoverflow.com/a/35621736/308315


Pas directement. Tu vas devoir:

  1. Créer un CAShapeLayer
  2. Définissez son pathpour être CGPathRefbasé sur view.boundsmais avec seulement deux coins arrondis (probablement en utilisant +[UIBezierPath bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:])
  3. Définissez votre view.layer.mask pour être leCAShapeLayer
Kurt Revis
la source
21
Soyez averti que cela nuira aux performances si vous le faites sur plus que quelques vues ...
jjxtra
@jjxtra Alors, quelle est la meilleure façon de le faire sans perte de performances importante? Je veux le montrer dans UITableViewCell.
xi.lin
@ xi.lin d'après ce dont je me souviens avoir défini layer.shouldRasterize == YES améliore la vitesse environ 5 fois. Mais la documentation dit que cela ne fonctionne que si vous travaillez avec des cellules non transparentes. Donner un coup de feu.
codrut
64

Voici une courte méthode implémentée comme ceci:

- (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
la source
Et la couleur? maskLayer.borderWidth = 10; maskLayer.borderColor = [UIColor redColor] .CGColor; ça ne marche pas pour moi monsieur.
kiran
1
@kiran un masque n'a pas de couleur, vous pouvez ajouter un deuxième CAShapeLayer si vous voulez avoir une bordure
Johnny Rockex
25

Dans swift 4.1 et Xcode 9.4.1

Dans iOS 11, cette seule ligne suffit:

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

Voir le code complet:

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

Mais pour les versions inférieures

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

Le code complet est.

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 vous utilisez le redimensionnement automatique dans le storyboard, écrivez ce code dans 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
la source
1
Cela ne fonctionne pas iOS 9 mais fonctionne le 11
Ali Ihsan URAL
Une solution pour iOS 9?
jey
@jay let rectShape = CAShapeLayer () rectShape.bounds = detailsSubView.frame rectShape.position = detailsSubView.center rectShape.path = UIBezierPath (roundRect: detailsSubView.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGS 20, hauteur: 20)). CgPath detailsSubView.layer.mask = rectShape Ce code peut fonctionner pour iOS 9
iOS
@jay check if not not me
iOS
Ne fonctionne pas pour iOS 9. Il n'y a pas de bordure sur la partie d'angle.
jey
24

iOS 11, Swift 4
Et vous pouvez essayer ce code:

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

Et vous pouvez l'utiliser dans la cellule de vue de table.

reza_khalafi
la source
1
c'est la bonne réponse pour le codage d'aujourd'hui. bye bye pour masquer le calque.
Alen Liang
1
Ce doit être la meilleure réponse!
fujianjin6471
18

Ce serait la réponse la plus simple:

yourView.layer.cornerRadius = 8
yourView.layer.masksToBounds = true
yourView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
pierre23
la source
tag que c'est la solution pour iOS 11 ou supérieur
Ankur Lahiry
16

Essayez ce code,

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;

la source
15

Emma: .TopRightet .BottomRightne travaillent pas pour vous peut-être parce que l'appel à view.roundCornersfait avant la finale view boundsest calculé. Notez que le Bezier Pathdérive des limites de la vue au moment de son appel. Par exemple, si la mise en page automatique réduit la vue, les coins arrondis du côté droit peuvent être en dehors de la vue. Essayez de l'appeler viewDidLayoutSubviews, où la limite de la vue est définitive.

David Barta
la source
Je vous remercie. Pour moi, ce qui a résolu le problème était de déplacer l'appel à l'implémentation donnée par "Arbitur" de viewDidLoad et viewWillAppear à viewDidAppear. Je pourrais le faire car mon contrôle est initialement défini sur caché.
Matti
Tu as raison. Cela créera un problème avec la mise en page automatique et vous avez fait du bon travail.
Ashish Kakkad
15

Swift 4 Swift 5 facile en 1 ligne

Usage:

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

Une fonction:

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

Dans Objective-C

Usage:

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

Fonction utilisée dans une catégorie (un seul coin):

-(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
la source
N'oubliez pas que les coins de votre vue ne sont pas calculés tant que le viewDidLayoutSubviews n'est pas terminé, vous devez donc appeler roundCorners func à l'intérieur
Jirson Tavera
pouvez-vous dire comment puis-je ajouter une ombre à cette vue?
Vadlapalli Masthan
@ShakeelAhmed, cela ne fonctionnera pas si vous souhaitez ajouter une ombre à la vue.
mojtaba al moussawi le
ajouter d'abord le rayon du coin, puis ajouter l'ombre
Shakeel Ahmed
10

Ma solution pour arrondir des coins spécifiques de UIView et UITextFiels en swift est d'utiliser

.layer.cornerRadius

et

layer.maskedCorners

des UIView ou UITextFields réels.

Exemple:

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
    }

Et en utilisant

.layerMaxXMaxYCorner

et

.layerMaxXMinYCorner

, Je peux spécifier le coin supérieur droit et le coin inférieur droit de l'UITextField à arrondir.

Vous pouvez voir le résultat ici:

entrez la description de l'image ici

Bane M
la source
Parfait pour la combinaison de bordures et de coins spécifiques 🎉🎉🎉
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
la source
Vous avez sauvé ma journée dans mon cas, j'ai dû arrondir la vue de la table pour des cellules particulières
Shakti
Parfait et selon mes besoins. J'ai utilisé toute la réponse, rien n'a fonctionné pour moi, mais votre réponse m'a aidé et a résolu mon problème.
Nikita Patil
6

Une façon de le faire par programme serait de créer un UIViewsur la partie supérieure de la UIViewqui a les coins arrondis. Ou vous pouvez cacher le haut sous quelque chose.

Nate Symer
la source
6
C'est une solution très moche: 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
la source
4

La façon la plus simple serait de créer un masque avec une couche de coins arrondis.

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

aUIView.layer.mask = maskLayer;

Et n'oubliez pas de:

#import <QuartzCore/QuartzCore.h>
Matt Hudson
la source
4

Toutes les réponses déjà données sont vraiment bonnes et valables (en particulier l'idée de Yunus d'utiliser la maskpropriété).

Cependant, j'avais besoin de quelque chose d'un peu plus complexe car ma couche pouvait souvent changer de taille, ce qui signifiait que je devais appeler cette logique de masquage à chaque fois et c'était un peu ennuyeux.

J'ai utilisé des extensionspropriétés rapides et calculées pour construire une cornerRadiipropriété réelle qui s'occupe de la mise à jour automatique du masque lorsque le calque est disposé.

Cela a été réalisé en utilisant les grands aspects de Peter Steinberg bibliothèque pour le swizzling.

Le code complet est ici:

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

J'ai écrit un simple billet de blog expliquant cela.

apouche
la source
2

Voici comment définir un rayon d'angle pour chaque coin d'un bouton avec 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
la source
2

Une belle extension pour réutiliser la solution 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
} }

Usage

let view = UIView()
view.roundCornersWithLayerMask(10,[.TopLeft,.TopRight])
apinho
la source
Belle solution propre
Aggressor
1

Après le changement de bit de code @apinho Dans swift 4.3 fonctionne 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
  }
}

Pour utiliser cette fonction pour vous afficher

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

Une autre version de la réponse de Stéphane .

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
la source
0

Dans Swift 4.2, créez-le via @IBDesignablecomme ceci:

@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
la source
0

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

Usage:

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