在iOS中,对CALayer进行描边掩码处理

13

我正在尝试创建一个带有一个圆角和描边/边框的标签(或者其他视图)。我可以使用以下代码实现圆角效果:

UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.label.bounds
                                      byRoundingCorners:UIRectCornerBottomRight
                                            cornerRadii:CGSizeMake(16.0f, 16.0f)];

CAShapeLayer *shape = [CAShapeLayer layer];
shape.frame = self.label.bounds;
shape.path = maskPath.CGPath;

self.label.layer.mask = shape;

对于圆角来说,这很好用,但是使用下面的代码不能按照我想要的方式应用描边。相反,它产生了一个黑色(或者与self.labelbackgroundColor设置相同的颜色)的方形边框。

UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.label.bounds
                                      byRoundingCorners:UIRectCornerBottomRight
                                            cornerRadii:CGSizeMake(16.0f, 16.0f)];

CAShapeLayer *shape = [CAShapeLayer layer];
shape.frame = self.label.bounds;
shape.path = maskPath.CGPath;

// Add stroke
shape.borderWidth = 1.0f;
shape.borderColor = [UIColor whiteColor].CGColor;

self.label.backgroundColor = [UIColor blackColor];
self.label.layer.mask = shape;

你有什么建议,我怎样可以应用一个随着被遮罩路径移动的任意颜色描边?

2个回答

38

你在形状图层方面已经走在了正确的道路上。但是你应该有两个不同的图层。首先是像第一个例子中的遮罩层,它可以遮盖你的视图(切掉你不想显示的区域)。

然后你也要添加形状层,但不要将其作为遮罩层。而且,请确保不使用borderWidth和borderColor,而是使用stroke。

//
// Create your mask first
//
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.label.bounds
                                      byRoundingCorners:UIRectCornerBottomRight
                                            cornerRadii:CGSizeMake(16.0f, 16.0f)];

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

//
// And then create the outline layer
//
CAShapeLayer *shape = [CAShapeLayer layer];
shape.frame = self.label.bounds;
shape.path = maskPath.CGPath;
shape.lineWidth = 3.0f;
shape.strokeColor = [UIColor whiteColor].CGColor;
shape.fillColor = [UIColor clearColor].CGColor;
[self.label.layer addSublayer:shape];

请注意,描边层路径应在遮罩路径内(小于)。否则,描边路径将被遮罩层遮掩。我将线条宽度设置为3,这样可以看到宽度的一半(1.5像素),另一半会在遮罩外面。


那样做有点用,但现在标签的文本被“形状”层覆盖了 :( - Steve Wilford
1
好的,我已经成功地将掩码应用到了 UIView 上,并将 UILabel 添加为其子视图。非常感谢 :) - Steve Wilford
8
StrokeLayer覆盖了标签,所以我加了这个代码来修复它:shape.fillColor = [UIColor clearColor].CGColor - name-it

0
如果你子类化CALayer,你可以用你想要的蒙版实例化它,并重载layoutSubLayers以包含你想要的边框在该蒙版上。
有几种方法可以做到这一点。下面我将使用给定蒙版的path,并将其分配给类属性,以用于在layoutSubLayers中构建新的边框。这种方法可能会被多次调用,因此我还设置了一个布尔值来跟踪这一点。(也可以将边框分配为类属性,并在每次删除/重新添加时进行操作。目前,我使用bool检查。) Swift 3:
class CustomLayer: CALayer {

    private var path: CGPath?
    private var borderSet: Bool = false

    init(maskLayer: CAShapeLayer) {
        super.init()
        self.path = maskLayer.path
        self.frame = maskLayer.frame
        self.bounds = maskLayer.bounds
        self.mask = maskLayer
    }

    override func layoutSublayers() {

        let newBorder = CAShapeLayer()

        newBorder.lineWidth = 12
        newBorder.path = self.path
        newBorder.strokeColor = UIColor.black.cgColor
        newBorder.fillColor = nil


        if(!borderSet) {
            self.addSublayer(newBorder)
            self.borderSet = true
        }

    }

    required override init(layer: Any) {
        super.init(layer: layer)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

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