在swift中创建一个只有两个圆角的矩形?

Mar*_*alc 38 core-graphics ios swift

我需要在swift中创建一个只有两个圆角的矩形(Objective C代码也可以).

目前我的代码正在创建两个矩形

CGPathCreateWithRoundedRect(CGRectMake(0, 0, 30, 60), 5, 5, nil);
Run Code Online (Sandbox Code Playgroud)

CGPathCreateWithRoundedRect(CGRectMake(0, 0, 30, 60), 0, 0, nil);
Run Code Online (Sandbox Code Playgroud)

合并它们(有两个直角和两个圆角)但我对代码不满意,我很确定应该有更好的方法来做到这一点.

我是iOS和图形开发的新手.

iwa*_*bed 66

这是一个快速Swift 3扩展,您可以使用它来进行舍入和可选边框.

注意:如果您正在使用autolayout,则可能需要在视图生命周期回调之一中viewDidLayoutSubviewslayoutSubviews在视图受限制之后调用此方法.

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

}
Run Code Online (Sandbox Code Playgroud)

  • 更新:只需要调用`viewDidLayoutSubviews`中的扩展名 (5认同)
  • 注意`addBorder(mask:borderColor:borderWidth :))方法,因为它总是添加一个新层.如果在一个空的UIView中使用`round(corner:radius:borderColor:borderWidth :))方法调用`viewDidLayoutSubviews`或`layoutSubviews` 5次...该视图将有5个子图层! (2认同)

San*_*ani 48

Swift 2.3中你可以这样做

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
Run Code Online (Sandbox Code Playgroud)

Objective-C中,您可以使用UIBezierPath类方法

bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:
Run Code Online (Sandbox Code Playgroud)

示例实施 -

// 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;
}
Run Code Online (Sandbox Code Playgroud)

并将上述方法称为 -

[self setMaskTo:anyView byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight];
Run Code Online (Sandbox Code Playgroud)

  • 不适合底层.即bottomLeft&bottomRight (3认同)

wca*_*art 31

Swift 4 +,iOS 11+

如果您已将UIView名称myView引用为an IBOutlet,请尝试ViewDidLoad()在其中加载以下两行:

myView.layer.cornerRadius = 10
myView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
Run Code Online (Sandbox Code Playgroud)

可以将阵列改变[]到的任何组合MinX,MinY,MaxX,和MaxY选择所需的角落.上面的例子围绕底部两个角.

这只是另一种方法,根据您的设计可能会更简单一些.

  • 重要警告,此解决方案仅适用于 iOS 11+ (2认同)

bud*_*ino 22

Swift 3 - UIView当您需要对某些视图的特定角进行舍入时的有用扩展:

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
  }
}
Run Code Online (Sandbox Code Playgroud)

然后就像这样使用它:

someView.round(corners: [.topLeft, .topRight], radius: 5)
Run Code Online (Sandbox Code Playgroud)


Eri*_*ric 11

在Sanjay的优秀答案的基础上,我为Swift 2.3编写了一个快速的CALayer扩展,以防你需要不止一次地做这种"只围绕某些角落"的事情.

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
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

myView.layer.roundCorners([.TopLeft, .TopRight], radius: myCornerRadius)
Run Code Online (Sandbox Code Playgroud)

Swift 3.0(在这个例子中,边界来自视图而不是来自图层.使用视图中的边界使得此代码可以在UITableViewCell中使用视图.):

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
}
Run Code Online (Sandbox Code Playgroud)

用法:

myView.layer.roundCorners(corners: [.topLeft, .topRight], radius: myCornerRadius, viewBounds: bounds)
Run Code Online (Sandbox Code Playgroud)


小智 9

仅限 iOS 11+ | 您可以在此处查看 iOS 使用情况统计信息

解释

由于CACornerMaskrawValue 是一个UInt你知道一个CACornerMask rawValue是每个rawValue的总和CACornerMask.Element

进一步来说:

  • 左上角 ( layerMinXMinYCorner) = 1
  • 右上 ( layerMaxXMinYCorner) = 2
  • 左下角 ( layerMinXMaxYCorner) = 4
  • 右下角 ( layerMaxXMaxYCorner) = 8

因此,例如,如果您想要左上角右上角,则只需键入CACornerMask(rawValue: 3).


 例子

下面是一个简单的扩展 UIView

extension UIView {
    enum Corner:Int {
        case bottomRight = 0,
        topRight,
        bottomLeft,
        topLeft
    }
    
    private func parseCorner(corner: Corner) -> CACornerMask.Element {
        let corners: [CACornerMask.Element] = [.layerMaxXMaxYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMinXMinYCorner]
        return corners[corner.rawValue]
    }
    
    private func createMask(corners: [Corner]) -> UInt {
        return corners.reduce(0, { (a, b) -> UInt in
            return a + parseCorner(corner: b).rawValue
        })
    }
    
    func roundCorners(corners: [Corner], amount: CGFloat = 5) {
        layer.cornerRadius = amount
        let maskedCorners: CACornerMask = CACornerMask(rawValue: createMask(corners: corners))
        layer.maskedCorners = maskedCorners
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以像这样使用它:

let myRect = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 50))
myRect.roundCorners(corners: [.topRight, .topLeft])
Run Code Online (Sandbox Code Playgroud)


And*_*ndy 8

这是你在Swift 2.0中所做的

var maskPath = UIBezierPath(roundedRect: anyView.bounds,
        byRoundingCorners: [.BottomLeft, .BottomRight],
        cornerRadii: CGSize(width: 10.0, height: 10.0))
Run Code Online (Sandbox Code Playgroud)


Fat*_*tie 7

2017年...

在此输入图像描述

@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
    }
}
Run Code Online (Sandbox Code Playgroud)

仅限某些角落,只需更改为:

在此输入图像描述

roundedRect: self.bounds,
  byRoundingCorners: [.topLeft, .topRight],
  cornerRadii: CGSize(width: r, height: r)
Run Code Online (Sandbox Code Playgroud)

请注意,像往常一样,Swift中有许多小的变化,例如常量的大写等.