551 Stimmen

Wie kann man den cornerRadius nur für die obere linke und obere rechte Ecke einer UIView festlegen?

Gibt es eine Möglichkeit, den cornerRadius nur für die obere linke und obere rechte Ecke einer UIView zu setzen?

Ich habe Folgendes versucht, aber danach konnte ich die Ansicht nicht mehr sehen.

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;

9 Stimmen

Nach Ihrer Bearbeitung drei Dinge zu beheben: (1) der abgerundete Pfad sollte auf view.bounds basieren, nicht auf frame, (2) die Ebene sollte ein CAShapeLayer sein, nicht CALayer; (3) setzen Sie den path der Ebene, nicht shadowPath.

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.

4voto

Matt Hudson Punkte 7299

Der einfachste Weg wäre, eine Maske mit einer abgerundeten Ecken Schicht zu erstellen.

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

aUIView.layer.mask = maskLayer;

Und vergessen Sie nicht:

#import

4voto

apouche Punkte 9443

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.

3voto

apinho Punkte 2165

Eine schöne Erweiterung zur Wiederverwendung der Lösung von 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
} }

Verwendung

let view = UIView()
view.roundCornersWithLayerMask(10,[.TopLeft,.TopRight])

3voto

Akshay Khadke Punkte 91

Verwenden Sie diese Erweiterung, um die Ecken abzurunden und einen runden Rand mit abgerundeten Ecken zu setzen

Verwenden Sie es wie folgt :

override func viewWillLayoutSubviews() {
            super.viewWillLayoutSubviews()

         myView.roundCornersWithBorder(corners: [.topLeft, .topRight], radius: 8.0)

        myView.roundCorners(corners: [.topLeft, .topRight], radius: 8.0)

        }

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
    }

    func roundCornersWithBorder(corners: UIRectCorner, radius: CGFloat) {
        let maskLayer = CAShapeLayer()
        maskLayer.frame = bounds
        maskLayer.path = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: radius, height: radius)).cgPath

        layer.mask = maskLayer

        // Rand hinzufügen
        let borderLayer = CAShapeLayer()
        borderLayer.path = maskLayer.path // Verwenden des Bezier-Pfads erneut
        borderLayer.fillColor = UIColor.clear.cgColor
        borderLayer.strokeColor = UIColor(red:3/255, green:33/255, blue:70/255, alpha: 0.15).cgColor
        borderLayer.lineWidth = 2
        borderLayer.frame = bounds
        layer.addSublayer(borderLayer)
    }

}

3voto

Bruno Bieri Punkte 8713

Wenn Sie nur nach einer Interface Builder-Lösung suchen, gibt es eine für iOS 11 und höher. Sehen Sie meine Antwort hier: https://stackoverflow.com/a/58626264

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X