Круглые верхние углы UIView и добавить границу

У меня есть следующий код в категории, который округляет углы. Я также хотел бы сделать границу. Но граница не показана на закругленной части угла.

enter image description here

Вот код

- (void) roundTopCorners:(CGFloat) radius
{
    self.layer.masksToBounds = YES;

    CGRect bounds = self.bounds;
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:bounds byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerTopRight) cornerRadii:CGSizeMake(radius, radius)];

    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.frame = bounds;
    maskLayer.path = maskPath.CGPath;
    maskLayer.strokeColor = [UIColor redColor].CGColor;

    self.layer.mask = maskLayer;
}

Ответы

Ответ 1

Уровень маски не нарисован, просто используется для вычисления маски. Попробуйте:

-(void)roundCorners:(UIRectCorner)corners radius:(CGFloat)radius
{
    CGRect bounds = self.bounds;
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:bounds
                                                   byRoundingCorners:corners
                                                         cornerRadii:CGSizeMake(radius, radius)];

    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.frame = bounds;
    maskLayer.path = maskPath.CGPath;

    self.layer.mask = maskLayer;

    CAShapeLayer*   frameLayer = [CAShapeLayer layer];
    frameLayer.frame = bounds;
    frameLayer.path = maskPath.CGPath;
    frameLayer.strokeColor = [UIColor redColor].CGColor;
    frameLayer.fillColor = nil;

    [self.layer addSublayer:frameLayer];
}

-(void)roundTopCornersRadius:(CGFloat)radius
{
    [self roundCorners:(UIRectCornerTopLeft|UIRectCornerTopRight) radius:radius];
}

-(void)roundBottomCornersRadius:(CGFloat)radius
{
    [self roundCorners:(UIRectCornerBottomLeft|UIRectCornerBottomRight) radius:radius];
}

Кадр, который вы видите в данный момент, представляет собой обычный кадр UITextField, поэтому установите стиль рамки равным none. Вам также нужно будет отрегулировать вставки, чтобы восполнить тот факт, что при установленном стандарте фрейма нет ни одной вставки.

Ответ 2

Быстрая версия ответа Дэвид Берри:

func roundCorners(corners:UIRectCorner, radius:CGFloat) {
    let bounds = self.bounds

    let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSizeMake(radius, radius))

    let maskLayer = CAShapeLayer()
    maskLayer.frame = bounds
    maskLayer.path = maskPath.CGPath

    self.layer.mask = maskLayer

    let frameLayer = CAShapeLayer()
    frameLayer.frame = bounds
    frameLayer.path = maskPath.CGPath
    frameLayer.strokeColor = UIColor.redColor().CGColor
    frameLayer.fillColor = nil

    self.layer.addSublayer(frameLayer)
}

func roundTopCornersRadius(radius:CGFloat) {
    self.roundCorners([UIRectCorner.TopLeft, UIRectCorner.TopRight], radius:radius)
}

func roundBottomCornersRadius(radius:CGFloat) {
    self.roundCorners([UIRectCorner.BottomLeft, UIRectCorner.BottomRight], radius:radius)
}

Ответ 3

это, вероятно, очень поздний ответ, но я хотел бы поделиться решением, которое я придумал, на основе ответов разных людей из разных похожих вопросов. Я получил большую помощь от ответа Vojtech выше.

extension UIView {
    func EZRoundCorners(corners:UIRectCorner, radius: CGFloat) -> CAShapeLayer {
        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
        return mask
    }

    func EZRoundCornersWithBorder(corners:UIRectCorner, radius:CGFloat, color:UIColor, width:CGFloat) -> CAShapeLayer {

        let mask = self.EZRoundCorners(corners, radius: radius)

        // Add border
        let borderLayer = EZCALayer()
        borderLayer.path = mask.path // Reuse the Bezier path
        borderLayer.fillColor = UIColor.clearColor().CGColor
        borderLayer.strokeColor = color.CGColor
        borderLayer.lineWidth = width
        borderLayer.frame = self.bounds
        self.layer.addSublayer(borderLayer)
        return borderLayer
    }

    func removeEZLayers () {
        for layer in self.layer.sublayers! {
            if layer is EZCALayer {
                layer.removeFromSuperlayer()
            }
        }
    }
}

class EZCALayer : CAShapeLayer {
}

Я унаследовал от CAShapeLayer, поэтому я могу удалить пограничные подслои, если я больше не хочу их использовать.