我创建了一个 UIView 子类,它具有渐变边框,背景为黄色。
class GradientBorderView: UIView {
override func layoutSubviews() {
super.layoutSubviews()
addGradientBorder()
}
private func addGradientBorder() {
self.layer.cornerRadius = 24
self.backgroundColor = UIColor.yellow
// Remove any existing layers
self.layer.sublayers?.removeAll(where: { $0.name == "gradientBorder" })
// Create the gradient layer
let gradientLayer = CAGradientLayer()
gradientLayer.name = "gradientBorder"
gradientLayer.frame = bounds
// Define the gradient colors
gradientLayer.colors = [UIColor.red.withAlphaComponent(0.2).cgColor, UIColor.black.withAlphaComponent(0.2).cgColor]
// Create a shape layer that defines the rounded path and border width
let shapeLayer = CAShapeLayer()
shapeLayer.lineWidth = 4 // gradient border width
shapeLayer.fillColor = UIColor.clear.cgColor //fill area will be transparent during masking
shapeLayer.strokeColor = UIColor.black.cgColor //stroke area will be visible during masking
//Half of the line width is drawn inside and other half of the line width is drawn outside the rectangle.
//Thats why oringal reactangle was shrunk from all side by half of the line width
shapeLayer.path = UIBezierPath(roundedRect: bounds.insetBy(dx: 2, dy: 2),
cornerRadius: self.layer.cornerRadius).cgPath
// Mask the gradient layer with the shape layer, only affecting the border
gradientLayer.mask = shapeLayer
// Add the gradient layer as a sublayer
layer.addSublayer(gradientLayer)
}
}
我无法摆脱角落处可见的额外黄色视图部分。
目标是使视图层与拐角处的渐变层平滑对齐。
另一种方法...
CAShapeLayer
.fillColor
和 .strokeColor
设置为黄色(或您想要使用的任何颜色).lineWidth
设置为与渐变边框相同的线宽然后,将基础形状图层的
.path
设置为与渐变图层相同的路径。
例如:
class AnotherGradientBorderView: UIView {
// let's use self's layer as a CAShapeLayer
override class var layerClass: AnyClass { CAShapeLayer.self }
private var selfLayer: CAShapeLayer { layer as! CAShapeLayer }
// border gradient
private var borderGradientLayer: CAGradientLayer = CAGradientLayer()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
// background needs to be clear
self.backgroundColor = .clear
selfLayer.fillColor = UIColor.yellow.cgColor
selfLayer.strokeColor = UIColor.yellow.cgColor
selfLayer.lineWidth = 4
borderGradientLayer.colors = [UIColor.red.withAlphaComponent(0.2).cgColor, UIColor.black.withAlphaComponent(0.2).cgColor]
self.layer.addSublayer(borderGradientLayer)
}
override func layoutSubviews() {
super.layoutSubviews()
borderGradientLayer.frame = bounds
// Create a shape layer that defines the rounded path and border width
let shapeLayer = CAShapeLayer()
shapeLayer.lineWidth = 4 // gradient border width
shapeLayer.fillColor = UIColor.clear.cgColor //fill area will be transparent during masking
shapeLayer.strokeColor = UIColor.black.cgColor //stroke area will be visible during masking
//Half of the line width is drawn inside and other half of the line width is drawn outside the rectangle.
//Thats why oringal reactangle was shrunk from all side by half of the line width
let pth = UIBezierPath(roundedRect: bounds.insetBy(dx: 2, dy: 2),
cornerRadius: 24.0).cgPath
shapeLayer.path = pth
// Mask the gradient layer with the shape layer, only affecting the border
borderGradientLayer.mask = shapeLayer
// set the path of self's layer (it is a CAShapeLayer) to
// match the path of the border layer
selfLayer.path = pth
}
}
输出: