如何使用CAShapeLayer创建圆角

12
有没有一种方法可以在CAShapeLayer中添加圆角? 在我的情况下,我需要使用lineDashPattern通过形状层创建虚线边框。 Rounded corners with dashed line - incorrect ^ 注意虚线不是圆角的。
2个回答

29
答案很简单。使用带有圆角的贝塞尔路径进行创建。
更新 Swift 版本。
view.clipsToBounds = true 
view.layer.cornerRadius = 10.0
let border = CAShapeLayer()
border.path = UIBezierPath(roundedRect:view.bounds, cornerRadius:10.0).cgPath
border.frame = view.bounds
border.fillColor = nil 
border.strokeColor = UIColor.purple.cgColor
border.lineWidth = borderWidth * 2.0 // doubled since half will be clipped
border.lineDashPattern = [15.0]
view.layer.addSublayer(border)

Objective-C

// (This old code assumes this is within a view with a custom property "border".)
self.clipsToBounds = YES; 
self.layer.cornerRadius = 10.0;

self.border = [CAShapeLayer layer];
self.border.fillColor = nil;
self.border.path = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:10.0].cgPath;
self.border.frame = self.bounds;
    
self.border.strokeColor = [UIColor purpleColor].CGColor;
self.border.lineWidth = borderWidth * 2; // double desired width as half will be clipped
self.border.lineDashPattern = @[@15];

[self.layer addSublayer:self.border];

正确的虚线圆角


这里的“self”是什么?因为CAShapeLayer没有borderclipsToBounds等属性,UIView也没有。 - HughHughTeotl
这是相当老的代码,但我相信self是一个自定义视图,具有类型为CAShapeLayer的属性border。(顺便说一下,UIViewclipsToBounds。) - David James
我认为 UIBezierPath 的问题在于需要将 cgPath 赋值给 .path。 - xaphod

0
在Swift 4中,我创建了一个UIView类别(UIView+Borders),其中包含以下函数:
func borderDash(withRadius cornerRadius: Float, borderWidth: Float, borderColor: UIColor, dashSize: Int) {
    let currentFrame = self.bounds
    let shapeLayer = CAShapeLayer()
    let path = CGMutablePath()
    let radius = CGFloat(cornerRadius)

    // Points - Eight points that define the round border. Each border is defined by two points.
    let topLeftPoint = CGPoint(x: radius, y: 0)
    let topRightPoint = CGPoint(x: currentFrame.size.width - radius, y: 0)
    let middleRightTopPoint = CGPoint(x: currentFrame.size.width, y: radius)
    let middleRightBottomPoint = CGPoint(x: currentFrame.size.width, y: currentFrame.size.height - radius)
    let bottomRightPoint = CGPoint(x: currentFrame.size.width - radius, y: currentFrame.size.height)
    let bottomLeftPoint = CGPoint(x: radius, y: currentFrame.size.height)
    let middleLeftBottomPoint = CGPoint(x: 0, y: currentFrame.size.height - radius)
    let middleLeftTopPoint = CGPoint(x: 0, y: radius)

    // Points - Four points that are the center of the corners borders.
    let cornerTopRightCenter = CGPoint(x: currentFrame.size.width - radius, y: radius)
    let cornerBottomRightCenter = CGPoint(x: currentFrame.size.width - radius, y: currentFrame.size.height - radius)
    let cornerBottomLeftCenter = CGPoint(x: radius, y: currentFrame.size.height - radius)
    let cornerTopLeftCenter = CGPoint(x: radius, y: radius)

    // Angles - The corner radius angles.
    let topRightStartAngle = CGFloat(Double.pi * 3 / 2)
    let topRightEndAngle = CGFloat(0)
    let bottomRightStartAngle = CGFloat(0)
    let bottmRightEndAngle = CGFloat(Double.pi / 2)
    let bottomLeftStartAngle = CGFloat(Double.pi / 2)
    let bottomLeftEndAngle = CGFloat(Double.pi)
    let topLeftStartAngle = CGFloat(Double.pi)
    let topLeftEndAngle = CGFloat(Double.pi * 3 / 2)

    // Drawing a border around a view.
    path.move(to: topLeftPoint)
    path.addLine(to: topRightPoint)
    path.addArc(center: cornerTopRightCenter,
                radius: radius,
                startAngle: topRightStartAngle,
                endAngle: topRightEndAngle,
                clockwise: false)
    path.addLine(to: middleRightBottomPoint)
    path.addArc(center: cornerBottomRightCenter,
                radius: radius,
                startAngle: bottomRightStartAngle,
                endAngle: bottmRightEndAngle,
                clockwise: false)
    path.addLine(to: bottomLeftPoint)
    path.addArc(center: cornerBottomLeftCenter,
                radius: radius,
                startAngle: bottomLeftStartAngle,
                endAngle: bottomLeftEndAngle,
                clockwise: false)
    path.addLine(to: middleLeftTopPoint)
    path.addArc(center: cornerTopLeftCenter,
                radius: radius,
                startAngle: topLeftStartAngle,
                endAngle: topLeftEndAngle,
                clockwise: false)

    // Path is set as the shapeLayer object's path.
    shapeLayer.path = path;
    shapeLayer.backgroundColor = UIColor.clear.cgColor
    shapeLayer.frame = currentFrame
    shapeLayer.masksToBounds = false
    shapeLayer.setValue(0, forKey: "isCircle")
    shapeLayer.fillColor = UIColor.clear.cgColor
    shapeLayer.strokeColor = borderColor.cgColor
    shapeLayer.lineWidth = CGFloat(borderWidth)
    shapeLayer.lineDashPattern = [NSNumber(value: dashSize), NSNumber(value: dashSize)]
    shapeLayer.lineCap = kCALineCapRound

    self.layer.addSublayer(shapeLayer)
    self.layer.cornerRadius = radius;
}

为什么要这样做,当你可以使用系统框架方法获得一个圆角矩形,就像接受的答案中所示? - jrturton
这是一个不同的答案。这是我如何使用虚线边框创建圆角视图的方法。 - Gastón Antonio Montes
1
我需要创建一个带有箭头(指向另一个UI元素)和带有拐角边框的Bezier路径。这个解决方案帮助我实现了它。 - Erich Flock

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接