Jak ustawić cornerRadius tylko dla lewego górnego i prawego górnego rogu UIView?

408

Czy można ustawić cornerRadiustylko lewy górny i prawy górny róg UIView?

Próbowałem następujących, ale ostatecznie nie zobaczyłem widoku.

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;
Tomek
źródło
9
Po zakończeniu edycji należy naprawić trzy rzeczy: (1) zaokrąglona ścieżka powinna opierać się na view.bounds, nie frame, (2) warstwa powinna być, a CAShapeLayernie CALayer; (3) ustaw warstwy path, a nie shadowPath.
Kurt Revis,
1
Możliwe duplikaty tego pytania i odpowiedzi .
Stuart
Użyj algorytmu krzywej Beziera, aby utworzyć krzywe na ścieżce CGPath. Jestem prawie pewien, że to część CoreGraphics. Jeśli nie, en.wikipedia.org/wiki/Bézier_curve ma kilka świetnych definicji i animacji.
Nate Symer
Zobacz moją odpowiedź tutaj: stackoverflow.com/a/50396485/6246128
wcarhart

Odpowiedzi:

224

Zwróć uwagę na fakt, że jeśli masz dołączone ograniczenia układu, musisz odświeżyć to w podklasie UIView w następujący sposób:

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

Jeśli tego nie zrobisz, nie pojawi się.


Aby zaokrąglać rogi, użyj rozszerzenia:

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
    }
}
Stéphane de Luca
źródło
3
Absolutnie nie jest to odpowiedź, autor pytał, jak zaokrąglać poszczególne rogi, a nie jak synchronizować promień narożnika ze zmianami układu.
kelin
1
To odpowiedź nie ma sensu.
Tiago Couto,
1
odpowiedź została ostatnio naprawiona .. @kelin
Michael
2
to zdecydowanie zaokrągliło róg.
aznelite89
Musisz to zrobić po pojawieniu się widoku
Jonathan.
535

Nie jestem pewien, dlaczego twoje rozwiązanie nie działało, ale poniższy kod działa dla mnie. Utwórz maskę Beziera i zastosuj ją do swojego widoku. W poniższym kodzie zaokrąglałem dolne rogi o _backgroundViewpromieniu 3 pikseli. selfto zwyczaj 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;

Wersja szybka z pewnymi ulepszeniami:

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

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

Wersja 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

Szybkie rozszerzenie tutaj

Yunus Nedim Mehel
źródło
2
spróbuj w polu tekstowym. sukces po lewej, porażka po prawej
Rainer Liao
10
@RainerLiao miałem ten sam problem, zrobiłem to wszystko w viewDidLoadmetodzie, przenieśliłem viewDidAppeari działało.
Lucho,
jak mogę ustawić to, aby działało na dowolnym urządzeniu. działa to dobrze tylko dla simulatorrozmiaru int storyboardu. ex: if the simulator size is 6s it works fine for 6s, but not of others.jak mogę to przezwyciężyć.
Chanaka Caldera
1
Mały błąd składniowy w wersji Swift 3: path.CGPathpowinien byćpath.cgPath
Rob
@RainerLiao, jeśli nie chcesz, aby migotało po wyświetleniu widoku, zmień go na viewWillAppear. To też działa.
Matthew Knippen,
263

Oto Swift wersja @JohnnyRockex odpowiedź

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)

Uwaga

Jeśli używasz automatycznego układu , musisz podklasować UIViewi wywoływać roundCornerswidok, layoutSubviewsaby uzyskać optymalny efekt.

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

        self.roundCorners([.topLeft, .bottomLeft], radius: 10)
    }
}
Arbitraż
źródło
12
Świetne rozszerzenie. Jednak: .TopRighti .BottomRightwydaje mi się, że nie działa dla mnie.
Onichan,
4
w Swift 2 :view.roundCorners([.TopLeft , .BottomLeft], radius: 10)
fahrulazmi
2
To nie działa na prawą stronę, ponieważ granice twojego widoku nie są jeszcze dobrze zdefiniowane przy pomocy autolayout ... Obecnie mam ten sam problem.
dosdos
3
@dosdos Podklasa, która zawiera widok i układ Podglądy za rogami siebie.
Arbitur
10
Jeśli korzystasz z automatycznego układu i nie masz odniesienia do widoku, który chcesz zaokrąglić, możesz wywołać .layoutIfNeeded()tę metodę.
zgjie
209

I wreszcie ... jest CACornerMask w iOS11! Dzięki CACornerMasktemu można to zrobić całkiem łatwo:

let view = UIView()
view.clipsToBounds = true
view.layer.cornerRadius = 10
view.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner] // Top right corner, Top left corner respectively
Sergey Belous
źródło
1
to zdecydowanie działa najlepiej. zawsze mieliśmy problemy z innymi rozwiązaniami podczas zaokrąglania krawędzi dynamicznie zmieniających rozmiar komórek widoku tabeli.
cornr
2
Projekt musi obsługiwać iOS 11 i nowsze, aby móc korzystać z tego rozwiązania.
Aliens
13
@ Aliens i… wspomniałem o tym.
Sergey Belous,
1
Inne odpowiedzi nie działają podczas obracania urządzenia, ten kod działa w przypadku obrotu i pozwala zaokrąglać określone rogi, powinna to być zaakceptowana odpowiedź.
Cloud9999Strife
1
Proste jest piękne
eharo2
99

Przykład szybkiego kodu tutaj: https://stackoverflow.com/a/35621736/308315


Nie bezpośrednio. Będziesz musiał:

  1. Stwórz CAShapeLayer
  2. Ustaw pathjako CGPathRefoparty na, view.boundsale z tylko dwoma zaokrąglonymi narożnikami (prawdopodobnie przy użyciu +[UIBezierPath bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:])
  3. Ustaw, view.layer.maskaby byćCAShapeLayer
Kurt Revis
źródło
21
Ostrzegamy, że zaszkodzi to wydajności, jeśli zrobisz to na więcej niż kilku widokach ...
jjxtra
@jjxtra Więc jaki jest najlepszy sposób, aby to zrobić bez dużej utraty wydajności? Chcę pokazać to w UITableViewCell.
xi.lin 18.04.16
@ xi.lin z tego co pamiętam ustawienie layer.shouldRasterize == TAK poprawia prędkość około 5 razy. Ale doktorzy mówią, że to działa tylko wtedy, gdy pracujesz z nieprzezroczystymi komórkami. Spróbuj.
codrut
64

Oto krótka metoda zaimplementowana w ten sposób:

- (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
źródło
Co z ustawieniem koloru? maskLayer.borderWidth = 10; maskLayer.borderColor = [UIColor redColor] .CGColor; to dla mnie nie działa.
kiran
1
@kiran maska ​​nie ma koloru, możesz dodać drugą CAShapeLayer, jeśli chcesz mieć obramowanie
Johnny Rockex
25

W wersji szybkiej 4.1 i Xcode 9.4.1

W iOS 11 ta pojedyncza linia wystarczy:

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

Zobacz pełny kod:

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

Ale dla niższych wersji

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

Pełny kod to.

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
}

Jeśli używasz AutoResizing w scenorysie, napisz ten kod w 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
źródło
1
To nie działa iOS 9, ale działa na 11
Ali Ihsan URAL
Jakieś rozwiązanie dla iOS 9?
jey
@jay niech rectShape = CAShapeLayer () rectShape.bounds = detailsSubView.frame rectShape.position = detailsSubView.center rectShape.path = UIBezierPath (roundedRect: detailsSubView.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize 20, wysokość: 20)). CgPath detailsSubView.layer.mask = rectShape Ten kod może działać w systemie iOS 9
iOS
@jay sprawdź, jeśli nie poinformuj mnie
iOS
Nie działa dla iOS 9. Jego nie ma granicy w części narożnej.
jey
24

iOS 11, Swift 4
I możesz wypróbować ten kod:

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

I możesz użyć tego w komórce widoku tabeli.

reza_khalafi
źródło
1
to właściwa odpowiedź na dzisiejsze kodowanie. pa pa do maskowania warstwy.
Alen Liang
1
To musi być najlepsza odpowiedź!
fujianjin6471
18

To byłaby najprostsza odpowiedź:

yourView.layer.cornerRadius = 8
yourView.layer.masksToBounds = true
yourView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
pierre23
źródło
tag, że jest to rozwiązanie dla iOS 11 lub
nowszego
16

Wypróbuj ten kod,

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;

źródło
15

Emma: .TopRighti .BottomRightnie pracują dla ciebie, być może dlatego, że wezwanie do view.roundCornerszostało wykonane PRZED końcowym view boundsobliczeniem. Zauważ, że Bezier Pathwywodzi się z granic widoku w momencie jego wywołania. Na przykład jeśli automatyczny układ zawęzi widok, zaokrąglone rogi po prawej stronie mogą znajdować się poza widokiem. Spróbuj to nazwać viewDidLayoutSubviews, gdzie granica widoku jest ostateczna.

David Barta
źródło
Dziękuję Ci. Dla mnie rozwiązaniem problemu było przeniesienie wywołania do implementacji podanej przez „Arbitur” z viewDidLoad i viewWillAppear do viewDidAppear. Mógłbym to zrobić, ponieważ początkowo moja kontrola jest ukryta.
Matti,
Masz rację. Stworzy to problem z autolayout i wykonałeś dobrą robotę.
Ashish Kakkad
15

Swift 4 Swift 5 łatwa droga w 1 linii

Stosowanie:

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

Funkcjonować:

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

W celu C

Stosowanie:

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

Funkcja używana w kategorii (tylko jeden róg):

-(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
źródło
Pamiętaj tylko, że narożniki widoku nie są obliczane, dopóki widok viewDidLayoutSubviews nie zostanie zrobiony, więc powinieneś wywołać funkcję roundCorners func wewnątrz niego
Jirson Tavera
czy możesz powiedzieć, jak mogę dodać cień do tych widoków?
Vadlapalli Masthan
@ShakeelAhmed to nie zadziała, jeśli chcesz dodać cień do widoku.
mojtaba al moussawi
najpierw dodaj promień narożnika, a następnie cień
Shakeel Ahmed
10

Moim rozwiązaniem do zaokrąglania określonych narożników UIView i UITextFiels w swift jest użycie

.layer.cornerRadius

i

layer.maskedCorners

rzeczywistych UIView lub UITextFields.

Przykład:

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
    }

I za pomocą

.layerMaxXMaxYCorner

i

.layerMaxXMinYCorner

, Mogę określić prawy górny i prawy dolny róg pola UITextField do zaokrąglenia.

Możesz zobaczyć wynik tutaj:

wprowadź opis zdjęcia tutaj

Bane M.
źródło
Idealny do kombinacji granicy i określonych narożników 🎉🎉🎉
nomnom
8

Szybki 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
źródło
Uratowałeś mi dzień w moim przypadku musiałem zaokrąglić widok tabeli dla poszczególnych komórek
Shakti
Idealne i zgodne z moimi wymaganiami. Użyłem całej odpowiedzi, nic nie działało dla mnie, ale twoja odpowiedź pomogła mi i rozwiązała mój problem.
Nikita Patil
6

Sposobem na zrobienie tego programowo byłoby utworzenie UIViewgórnej części z UIViewzaokrąglonymi narożnikami. Lub możesz ukryć górę pod czymś.

Nate Symer
źródło
6
To bardzo brzydkie rozwiązanie: 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;
Szpieg
źródło
4

Najprostszym sposobem byłoby zrobienie maski z zaokrągloną warstwą narożną.

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

aUIView.layer.mask = maskLayer;

I nie zapomnij:

#import <QuartzCore/QuartzCore.h>
Matt Hudson
źródło
4

Wszystkie podane już odpowiedzi są naprawdę dobre i poprawne (szczególnie pomysł Yunusa na użycie mask właściwości).

Potrzebowałem jednak czegoś nieco bardziej złożonego, ponieważ moja warstwa często zmieniała rozmiary, co oznacza, że ​​musiałem nazywać tę logikę maskowania za każdym razem, a to było trochę denerwujące.

Użyłem szybkich extensionsi obliczonych właściwości, aby zbudować prawdziwycornerRadii właściwość, która zajmuje się automatyczną aktualizacją maski po ułożeniu warstwy.

Zostało to osiągnięte dzięki doskonałym aspektom Petera Steinberga biblioteki do zamiatania.

Pełny kod jest tutaj:

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

Wyjaśniłem prosty post na blogu .

apouche
źródło
2

W ten sposób możesz ustawić promień narożnika dla każdego rogu przycisku za pomocą Xamarin w 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
źródło
2

Piękne rozszerzenie do ponownego wykorzystania rozwiązania 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
} }

Stosowanie

let view = UIView()
view.roundCornersWithLayerMask(10,[.TopLeft,.TopRight])
apinho
źródło
Ładne czyste rozwiązanie
Aggressor,
1

Po zmianie bit kodu @apinho W swift 4.3 działa dobrze

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

Aby użyć tej funkcji do przeglądania

YourViewName. roundCornersWithLayerMask(cornerRadii: 20,corners: [.topLeft,.topRight])
Sanjay Mishra
źródło
0

Inna wersja odpowiedzi Stephane'a .

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
źródło
0

W Swift 4.2 utwórz go w @IBDesignablenastępujący sposób:

@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
źródło
0

Proste rozszerzenie

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

Stosowanie:

view.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 12)
FunkyKat
źródło