Alle bereits gegebenen Antworten sind wirklich gut und gültig (insbesondere die Idee von Yunus, die die mask
-Eigenschaft verwendet).
Ich brauchte jedoch etwas Komplexeres, weil meine Ebene oft ihre Größe ändern konnte, was bedeutete, dass ich diese Maskenlogik jedes Mal aufrufen musste, und das war ein wenig lästig.
Ich habe Swift Extensions
und berechnete Eigenschaften verwendet, um eine echte cornerRadii
-Eigenschaft aufzubauen, die sich um das automatische Aktualisieren der Maske kümmert, wenn die Ebene ausgelegt wird.
Dies wurde mit der großartigen Aspects-Bibliothek von Peter Steinberg erreicht, um das Swizzling durchzuführen.
Der vollständige Code ist hier:
extension CALayer {
// Hier werden die Schlüssel für die Laufzeit-Property-Assoziationen gehalten
private struct AssociationKey {
static var CornerRect:Int8 = 1 // für das UIRectCorner-Argument
static var CornerRadius:Int8 = 2 // für das Radius-Argument
}
// Neue berechnete Eigenschaft auf CALayer
// Du gibst die Ecken an, die gerundet werden sollen (z.B. [.TopLeft, .BottomLeft])
// und den Radius, mit dem die Ecken gerundet werden sollen
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 _ { }
}
}
}
Ich habe einen einfachen Blog-Beitrag verfasst, der dies erklärt.
9 Stimmen
Nach Ihrer Bearbeitung drei Dinge zu beheben: (1) der abgerundete Pfad sollte auf
view.bounds
basieren, nicht aufframe
, (2) die Ebene sollte einCAShapeLayer
sein, nichtCALayer
; (3) setzen Sie denpath
der Ebene, nichtshadowPath
.1 Stimmen
Möglicher Duplikat dieser Frage & Antwort.
0 Stimmen
Verwenden Sie den Bezier-Kurvenalgorithmus, um Kurven auf einem CGPath zu erstellen. Ich bin mir ziemlich sicher, dass es Teil von CoreGraphics ist. Wenn nicht, hat en.wikipedia.org/wiki/Bézier_curve einige großartige Definitionen und Animationen.
0 Stimmen
iosdevcenters.blogspot.com/2018/02/…
0 Stimmen
Siehe meine Antwort hier: stackoverflow.com/a/50396485/6246128
0 Stimmen
Es ist auf iOS 11 und höher viel einfacher: johncodeos.com/…
0 Stimmen
IOS 11 - Lösung nur für den Interface Builder: stackoverflow.com/a/58626264