Hızlıca iki yuvarlatılmış köşeleri olan bir dikdörtgen mi oluşturun?

Hızlıca iki yuvarlatılmış köşesi olan bir dikdörtgen oluşturmam gerekiyor (Objective C code ayrıca tamam).

Şu anda kodum iki dikdörtgen oluşturuyor

CGPathCreateWithRoundedRect(CGRectMake(0, 0, 30, 60), 5, 5, nil);

ve

CGPathCreateWithRoundedRect(CGRectMake(0, 0, 30, 60), 0, 0, nil);

vemerging them (to have two right angle corners vetwo rounded ones) but I am not happy with the code veI am pretty sure there should be much better ways to do it.

I am new to iOS vegraphical development veswift.

27
Her zamanki gibi, Swift'de * birçok küçük değişiklik oldu, örneğin sabitlerin büyük harfleri, vb.
katma yazar Fattie, kaynak
developer.apple.com/library/ios/documentation/UIKit/Referenc‌ e/& hellip; : bezierPathWithRoundedRect: byRoundingCorners: cornerRadii:
katma yazar matt, kaynak

10 cevap

İşte yuvarlama ve isteğe bağlı kenarlıklar yapmak için kullanabileceğiniz hızlı bir Swift 3 uzantısı.

Not: Otomatik yerleşimi kullanıyorsanız, görünüm kısıtlandıktan sonra bunu viewDidLayoutSubviews veya layoutSubviews gibi görünüm yaşam döngüsü geri aramalarından birinde çağırmanız gerekebilir.

import UIKit

extension UIView {

    /**
     Rounds the given set of corners to the specified radius

     - parameter corners: Corners to round
     - parameter radius:  Radius to round to
     */
    func round(corners: UIRectCorner, radius: CGFloat) {
        _ = _round(corners: corners, radius: radius)
    }

    /**
     Rounds the given set of corners to the specified radius with a border

     - parameter corners:     Corners to round
     - parameter radius:      Radius to round to
     - parameter borderColor: The border color
     - parameter borderWidth: The border width
     */
    func round(corners: UIRectCorner, radius: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
        let mask = _round(corners: corners, radius: radius)
        addBorder(mask: mask, borderColor: borderColor, borderWidth: borderWidth)
    }

    /**
     Fully rounds an autolayout view (e.g. one with no known frame) with the given diameter and border

     - parameter diameter:    The view's diameter
     - parameter borderColor: The border color
     - parameter borderWidth: The border width
     */
    func fullyRound(diameter: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
        layer.masksToBounds = true
        layer.cornerRadius = diameter/2
        layer.borderWidth = borderWidth
        layer.borderColor = borderColor.cgColor;
    }

}

private extension UIView {

    @discardableResult func _round(corners: UIRectCorner, radius: CGFloat) -> CAShapeLayer {
        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        self.layer.mask = mask
        return mask
    }

    func addBorder(mask: CAShapeLayer, borderColor: UIColor, borderWidth: CGFloat) {
        let borderLayer = CAShapeLayer()
        borderLayer.path = mask.path
        borderLayer.fillColor = UIColor.clear.cgColor
        borderLayer.strokeColor = borderColor.cgColor
        borderLayer.lineWidth = borderWidth
        borderLayer.frame = bounds
        layer.addSublayer(borderLayer)
    }

}
60
katma
Bunlar bir UIButton ile çalışacak mı?
katma yazar Dave G, kaynak
@Onichan Otomatik düzenleme görünümleri için çalışan bir fullyRound yöntemi ekledim, çünkü çerçeve viewDidLoad kodundan çağrılmadıysa kurulmadı
katma yazar iwasrobbed, kaynak
@DaveG herhangi bir UIView alt sınıfı ile çalışır (örneğin, UIButton, UILabel, UITextField, vb.)
katma yazar iwasrobbed, kaynak
@Dincer bana normal görünüyor. Oyun alanı: gist.github.com/iwasrobbed/6ebd47d64b921ca27809ada = h4 /imgur.com/xZCZmO4 "rel =" nofollow noreferrer "> imgur.com/xZCZmO4 ... Daha spesifik olabilir misiniz?
katma yazar iwasrobbed, kaynak
@Dari Yukarıya bakın: viewDidLayoutSubviews yaşam döngüsü geri çağrısında
katma yazar iwasrobbed, kaynak
Bunu bir UITextField üzerinde kullanıyorum, ancak metin alanının genişliğini değiştiriyor. Genişliği neden değiştirir (Autolayout kullanılarak ayarlanmıştır).
katma yazar Onichan, kaynak
Güncelleme: uzantıyı viewDidLayoutSubviews içinden çağırmak zorunda kaldım
katma yazar Onichan, kaynak
sth yanlış için alt [.bottomLeft, .topLeft] olarak kullanarak yanlış
katma yazar JSBach, kaynak
Görüntüleme boyutum dinamik olduğunda bu nasıl kullanılır? Çok satırlı etiket diyelim. Fonksiyonu ne zaman yuvarlayayım?
katma yazar Dari, kaynak
@iwasrobbed func viewDidLayoutSubviews() içindeki bir düğmedeki round yöntemini arıyorum ve bu konumun ayarlanması/düğmesinin ayarlanması kadar çok fazla gecikme içeriyor. Ayrıca şunu da denedim: @IBOutlet fileprivate zayıf var düğmesi: UIButton! {didSet {button.round (corners: [.topRight, .bottomLeft], yarıçap: 50, borderColor: UIColor.blue, borderWidth: 5.0) button.layoutSubviews ()} gecikme şimdi gitti, ancak düğme hala küçültülmüş/düzgün şekilde sınırlandırılmamıştır. Teşekkürler! Teşekkürler!
katma yazar lifewithelliott, kaynak
lineWidth 'in ekran ölçeğini kontrol etmediğini unutmayın, bu nedenle borderWidth UIScreen.main.scale ile çarpılmalıdır.
katma yazar ricardopereira, kaynak
addBorder (mask: borderColor: borderWidth :) yöntemine dikkat edin, çünkü her zaman yeni bir katman ekler. Boş bir UIView'da round (köşeler: radius: borderColor: borderWidth :) yöntemini kullanarak viewDidLayoutSubviews veya layoutSubviews 5 kez çağrılırsa ... Bu görüntünün 5 alt katmanı olacak!
katma yazar ricardopereira, kaynak
Değişiklikleri göstermek için round() yöntemini çağırmadan önce görünümdeki self.layer.masksToBounds = true ayarlamam gerekiyordu.
katma yazar Sharukh Mastan, kaynak

Swift 2.3 'te bunu yapabilirsiniz

let maskPath = UIBezierPath(roundedRect: anyView.bounds,
            byRoundingCorners: [.BottomLeft, .BottomRight],
            cornerRadii: CGSize(width: 10.0, height: 10.0))

let shape = CAShapeLayer()
shape.path = maskPath.CGPath
view.layer.mask = shape

Hedef-C 'de UIBezierPath sınıf yöntemini kullanabilirsiniz.

bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:

örnek uygulama

// set the corner radius to the specified corners of the passed container
- (void)setMaskTo:(UIView*)view byRoundingCorners:(UIRectCorner)corners
{
    UIBezierPath *rounded = [UIBezierPath bezierPathWithRoundedRect:view.bounds
                                                  byRoundingCorners:corners
                                                        cornerRadii:CGSizeMake(10.0, 10.0)];
    CAShapeLayer *shape = [[CAShapeLayer alloc] init];
    [shape setPath:rounded.CGPath];
    view.layer.mask = shape;
}

ve yukarıdaki yöntemi

[self setMaskTo:anyView byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight];
31
katma
alt için çalışmıyor. diğer bir deyişle, alt ve alt
katma yazar user1673099, kaynak
Swift 4'te çalışmıyor. [.bottomLeft, .bottomRight] kullanarak Yalnızca alt köşede yuvarladım.
katma yazar Piotr Wasilewicz, kaynak
katma yazar Leo Dabus, kaynak
mükemmel, kesinlikle objektif-c #define olarak hızlı bir şekilde kullanılabilir
katma yazar Sanjay Mohnani, kaynak
ve - çift startAngle = RADIANS (45); çift ​​uçAngle = RADYANLAR (135);
katma yazar Sanjay Mohnani, kaynak
başlangıç ​​ve bitiş açılarını kullanmayı mı soruyorsunuz?
katma yazar Sanjay Mohnani, kaynak
#define RADIANS (derece) ((derece)/(180.0/M_PI))
katma yazar Sanjay Mohnani, kaynak
Cevabımla sorunumu çözebilirim. Ancak UIBezierPath.addArcWithCenter'ı yuvarlatılmış köşeleri kendim çizmek için kullanmaya başladığımdan ve başlangıç ​​ve bitiş açısının developer.apple.com/library/ios/documentation/UIKit/Referenc ve zwnj, e/ve hellip;
katma yazar Maralc, kaynak
hızlı 2.0'da bunu nasıl yapıyorsunuz? "|" işe görünmüyor
katma yazar Andy, kaynak

Swift 3 - Useful UIView extension when you need to round specific corners of some views:

extension UIView {
  func round(corners: UIRectCorner, radius: CGFloat) {
    let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
    let mask = CAShapeLayer()
    mask.path = path.cgPath
    self.layer.mask = mask
  }
}

o zaman sadece bu şekilde kullanın:

someView.round(corners: [.topLeft, .topRight], radius: 5)
10
katma
Teşekkürler .. benim için çalışıyor
katma yazar MAhipal Singh, kaynak

Sanjay'in mükemmel cevabına dayanarak, Swift 2.3 için hızlı bir CALayer uzantısı yazdım, bu tür "sadece bazı köşelere yuvarlak" bir şeyi birden fazla yapmanız gerekebilir diye yazdım.

extension CALayer {
  func roundCorners(corners: UIRectCorner, radius: CGFloat) {
    let maskPath = UIBezierPath(roundedRect: bounds,
                                byRoundingCorners: corners,
                                cornerRadii: CGSize(width: radius, height: radius))

    let shape = CAShapeLayer()
    shape.path = maskPath.CGPath
    mask = shape
  }
}

Kullanımı:

myView.layer.roundCorners([.TopLeft, .TopRight], radius: myCornerRadius)

Swift 3.0 (Bu örnekte, sınırlar katmandan değil görünümden geldi. Görünümdeki sınırları kullanarak bu kodu bir UITableViewCell'deki görünümlerle çalışmak için yapın.):

func roundCorners(corners: UIRectCorner, radius: CGFloat, viewBounds: CGRect) {

    let maskPath = UIBezierPath(roundedRect: viewBounds,
                                byRoundingCorners: corners,
                                cornerRadii: CGSize(width: radius, height: radius))

    let shape = CAShapeLayer()
    shape.path = maskPath.cgPath
    mask = shape
}

Kullanımı:

myView.layer.roundCorners(corners: [.topLeft, .topRight], radius: myCornerRadius, viewBounds: bounds)
10
katma
hi @satoukum - Modern Xcode'da bununla baş etmenin doğru yolu, cevabım aşağıda gösterilmiştir.
katma yazar Fattie, kaynak
(iyi olan - her zamanki gibi Swift'de çok küçük değişiklikler oldu, örneğin sabitlerin büyük harf kullanımı, vb.)
katma yazar Fattie, kaynak
Benim için bazen görüntü, üst köşeleri yuvarladığımda görünmüyordu, bu yüzden daha önce satırına myView.layoutIfNeeded() eklemem gerekiyordu.
katma yazar satoukum, kaynak

Here is what you do in Swift 2.0

var maskPath = UIBezierPath(roundedRect: anyView.bounds,
        byRoundingCorners: [.BottomLeft, .BottomRight],
        cornerRadii: CGSize(width: 10.0, height: 10.0))
8
katma
alt için çalışmıyor. diğer bir deyişle, alt ve alt
katma yazar user1673099, kaynak

2017 ...

enter image description here

@IBDesignable
class RoundedEnds: UIView {

    override func layoutSubviews() { setup() }//"layoutSubviews" is best

    func setup() {
        let r = self.bounds.size.height/2
        let path = UIBezierPath(roundedRect: self.bounds, cornerRadius:r)
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        self.layer.mask = mask
    }
}

Sadece bazı köşeler için, sadece değiştirin:

enter image description here

roundedRect: self.bounds,
  byRoundingCorners: [.topLeft, .topRight],
  cornerRadii: CGSize(width: r, height: r)

Her zamanki gibi Swift'de, örneğin sabitlerin büyük harf kullanımı, vb. Birçok küçük değişiklik olduğunu unutmayın.

6
katma

Swift 4+, iOS 11+

IBOutlet olarak adlandırılan myView adında bir UIView varsa, ViewDidLoad() veya yüklendiği her yerde:

myView.layer.cornerRadius = 10
myView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]

[] dizisini MinX , MinY , MaxX ve MaxY kombinasyonlarından herhangi biriyle değiştirebilirsiniz istenen köşeleri seçmek için. Yukarıdaki örnek alt iki köşeyi yuvarlar.

Bu sadece başka bir yaklaşım, tasarımınıza bağlı olarak biraz daha basit olabilir.

5
katma
büyük ihtar, bu çözüm sadece iOS 11+
katma yazar monolith, kaynak

Swift 3.0 GM sürümü ile çalışmak için iWasRobbed'ın cevabı güncellendi:

import UIKit

extension UIView {

    /**
     Rounds the given set of corners to the specified radius

     - parameter corners: Corners to round
     - parameter radius:  Radius to round to
     */
    func round(corners: UIRectCorner, radius: CGFloat) {
        _round(corners: corners, radius: radius)
    }

    /**
     Rounds the given set of corners to the specified radius with a border

     - parameter corners:     Corners to round
     - parameter radius:      Radius to round to
     - parameter borderColor: The border color
     - parameter borderWidth: The border width
     */
    func round(corners: UIRectCorner, radius: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
        let mask = _round(corners: corners, radius: radius)
        addBorder(mask: mask, borderColor: borderColor, borderWidth: borderWidth)
    }

    /**
     Fully rounds an autolayout view (e.g. one with no known frame) with the given diameter and border

     - parameter diameter:    The view's diameter
     - parameter borderColor: The border color
     - parameter borderWidth: The border width
     */
    func fullyRound(diameter: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
        layer.masksToBounds = true
        layer.cornerRadius = diameter/2
        layer.borderWidth = borderWidth
        layer.borderColor = borderColor.cgColor;
    }

}

private extension UIView {

    @discardableResult func _round(corners: UIRectCorner, radius: CGFloat) -> CAShapeLayer {
        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        self.layer.mask = mask
        return mask
    }

    func addBorder(mask: CAShapeLayer, borderColor: UIColor, borderWidth: CGFloat) {
        let borderLayer = CAShapeLayer()
        borderLayer.path = mask.path
        borderLayer.fillColor = UIColor.clear.cgColor
        borderLayer.strokeColor = borderColor.cgColor
        borderLayer.lineWidth = borderWidth
        borderLayer.frame = bounds
        layer.addSublayer(borderLayer)
    }

}
2
katma

İWasRobbed'in cevabının Amaç-C versiyonu:

UIView + RoundCorners.h

#import 

@interface UIView (RoundCorners)

/**
 Rounds the given set of corners to the specified radius

 - parameter corners: Corners to round
 - parameter radius:  Radius to round to
 */
- (void)roundCorners:(UIRectCorner)corners radius:(CGFloat)radius;

/**
 Rounds the given set of corners to the specified radius with a border

 - parameter corners:     Corners to round
 - parameter radius:      Radius to round to
 - parameter borderColor: The border color
 - parameter borderWidth: The border width
 */
- (void)roundCorners:(UIRectCorner)corners radius:(CGFloat)radius borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth;

/**
 Fully rounds an autolayout view (e.g. one with no known frame) with the given diameter and border

 - parameter diameter:    The view's diameter
 - parameter borderColor: The border color
 - parameter borderWidth: The border width
 */
- (void)fullyRoundWithDiameter:(CGFloat)diameter borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth;

@end

UIView + RoundCorners.m

#import "UIView + RoundCorners.h"

@implementation UIView (RoundCorners)

- (void)roundCorners:(UIRectCorner)corners radius:(CGFloat)radius {
    [self _roundCorners:corners radius:radius];
}

- (void)roundCorners:(UIRectCorner)corners radius:(CGFloat)radius borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth {
    CAShapeLayer *mask = [self _roundCorners:corners radius:radius];
    [self addBorderWithMask:mask borderColor:borderColor borderWidth:borderWidth];
}

- (void)fullyRoundWithDiameter:(CGFloat)diameter borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth {
    self.layer.masksToBounds = YES;
    self.layer.cornerRadius = diameter/2;
    self.layer.borderWidth = borderWidth;
    self.layer.borderColor = borderColor.CGColor;
}

- (CAShapeLayer *)_roundCorners:(UIRectCorner)corners radius:(CGFloat)radius {
    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(radius, radius)];
    CAShapeLayer *mask = [CAShapeLayer layer];
    mask.path = path.CGPath;
    self.layer.mask = mask;
    return mask;
}

- (void)addBorderWithMask:(CAShapeLayer *)mask borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth {
    CAShapeLayer *borderLayer = [CAShapeLayer layer];
    borderLayer.path = mask.path;
    borderLayer.fillColor = UIColor.clearColor.CGColor;
    borderLayer.strokeColor = borderColor.CGColor;
    borderLayer.lineWidth = borderWidth;
    borderLayer.frame = self.bounds;
    [self.layer addSublayer:borderLayer];
}

@end
1
katma

Swift 4:

    let maskPath = UIBezierPath(roundedRect: view.bounds,
                                byRoundingCorners: [.allCorners],
                                cornerRadii: CGSize(width: 10.0, height: 10.0))

    let shape = CAShapeLayer()
    shape.path = maskPath.cgPath
    cell.layer.mask = shape


    return cell
1
katma
ne Dört köşeden sadece üçünü istiyorsam? [.bottomLeft, .bottomRight, .topRight] çalışmıyor.
katma yazar Piotr Wasilewicz, kaynak