CAShapeLayer 具有边框和填充颜色以及舍入

Posted

技术标签:

【中文标题】CAShapeLayer 具有边框和填充颜色以及舍入【英文标题】:CAShapeLayer with border and fill color and rounding 【发布时间】:2012-10-06 05:11:38 【问题描述】:

如何使用 CAShapeLayer 绘制同时具有边框颜色、边框宽度和填充颜色的线条?

这是我尝试过的,但它永远是蓝色的......

self.lineShape.strokeColor = [UIColor blueColor].CGColor;
self.lineShape.fillColor = [UIColor greenColor].CGColor;
self.lineShape.lineWidth = 100;
self.lineShape.lineCap = kCALineCapRound;
self.lineShape.lineJoin = kCALineJoinRound;
UIBezierPath* path = [UIBezierPath bezierPath];
[path moveToPoint:self.lineStart];
[path addLineToPoint:self.lineEnd];
self.lineShape.path = path.CGPath;

【问题讨论】:

对于那些寻找“为什么不显示边框”的人:将 borderWidth 更改为 lineWidthborderColor 更改为 strokeColor 【参考方案1】:

Swift 3+ 扩展方法(结合下面的 AechoLiu 回答):

// Usage:
self.btnGroup.roundCorner([.topRight, .bottomRight], radius: 4.0, borderColor: UIColor.red, borderWidth: 1.0)

// Apply round corner and border. An extension method of UIView.
public func roundCorner(_ corners: UIRectCorner, radius: CGFloat, borderColor: UIColor, borderWidth: CGFloat) 

let path = UIBezierPath.init(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))

let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask

let borderPath = UIBezierPath.init(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let borderLayer = CAShapeLayer()
borderLayer.path = borderPath.cgPath
borderLayer.lineWidth = borderWidth
borderLayer.strokeColor = borderColor.cgColor
borderLayer.fillColor = UIColor.clear.cgColor
borderLayer.frame = self.bounds
self.layer.addSublayer(borderLayer)


目标-C:

self.lineShapeBorder = [[CAShapeLayer alloc] init];
self.lineShapeBorder.zPosition = 0.0f;
self.lineShapeBorder.strokeColor = [UIColor blueColor].CGColor;
self.lineShapeBorder.lineWidth = 25;
self.lineShapeBorder.lineCap = kCALineCapRound;
self.lineShapeBorder.lineJoin = kCALineJoinRound;
     
self.lineShapeFill = [[CAShapeLayer alloc] init];
[self.lineShapeBorder addSublayer:self.lineShapeFill];
self.lineShapeFill.zPosition = 0.0f;
self.lineShapeFill.strokeColor = [UIColor greenColor].CGColor;
self.lineShapeFill.lineWidth = 20.0f;
self.lineShapeFill.lineCap = kCALineCapRound;
self.lineShapeFill.lineJoin = kCALineJoinRound;
  
// ...
    
UIBezierPath* path = [UIBezierPath bezierPath];
[path moveToPoint:self.lineStart];
[path addLineToPoint:self.lineEnd];
// call addLineToPoint over and over to create the outline for the shape
self.lineShapeBorder.path = self.lineShapeFill.path = path.CGPath;

同时调用@FarrasDoko 评论以尝试将borderWidth 更改为lineWidthborderColor 更改为strokeColor

【讨论】:

我运气不好只使用一个路径和形状层,所以仍然坚持这个答案:) 结合 swift + obj 答案让程序员更容易消费 编辑后能否指出Swift版本的来源?谢谢。【参考方案2】:

如果您将图层的fillColor 属性设置为nil 以外的其他值或透明,则图层将填充其路径。

如果您将图层的lineWidth 设置为大于零的数字,并且将其strokeColor 设置为nil 以外的其他值或透明,则图层将描边其路径。

如果您设置了所有这些属性,图层将填充描边其路径。它在填充之后绘制笔触。

图层的路径实际上必须包围一些区域才能填充任何东西。在您的帖子中,您将路径设置为:

UIBezierPath* path = [UIBezierPath bezierPath];
[path moveToPoint:self.lineStart];
[path addLineToPoint:self.lineEnd];
self.lineShape.path = path.CGPath;

该路径包含一条线段。它没有包围任何区域,因此该层没有什么可填充的。

【讨论】:

那么我需要让我的路径是一个多边形吗? @PsychoDad 您的路径可以是多边形,也可以是弯曲的边。它必须具有非零面积。一条线段的面积为零。【参考方案3】:

在 Swift 3 中,UIView 的扩展方法。

// Usage:
self.btnGroup.roundCorner([.topRight, .bottomRight], radius: 4.0, borderColor: UIColor.red, borderWidth: 1.0)

// Apply round corner and border. An extension method of UIView.
public func roundCorner(_ corners: UIRectCorner, radius: CGFloat, borderColor: UIColor, borderWidth: CGFloat) 
    let path = UIBezierPath.init(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))

    let mask = CAShapeLayer()
    mask.path = path.cgPath
    self.layer.mask = mask

    let borderPath = UIBezierPath.init(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
    let borderLayer = CAShapeLayer()
    borderLayer.path = borderPath.cgPath
    borderLayer.lineWidth = borderWidth
    borderLayer.strokeColor = borderColor.cgColor
    borderLayer.fillColor = UIColor.clear.cgColor
    borderLayer.frame = self.bounds
    self.layer.addSublayer(borderLayer)

【讨论】:

以上是关于CAShapeLayer 具有边框和填充颜色以及舍入的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 R 中的 ggplot 绘制具有相同颜色的填充点和置信椭圆?

ggplot中geom_point(scale_colour_manual)中的填充和边框颜色

Android CheckBox 改变边框和填充色

无法在错误边框TextFormField Flutter中填充颜色

word边框+底纹

如何在 Flutter 中使我的单选按钮完全填充活动颜色的颜色而没有白色边框?