UView 圆角渐变边框的问题

问题描述 投票:0回答:1

我创建了一个 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)
        
    }
}

screenshot

我无法摆脱角落处可见的额外黄色视图部分。

目标是使视图层与拐角处的渐变层平滑对齐。

swift uiview core-graphics cashapelayer cagradientlayer
1个回答
0
投票

另一种方法...

  • 将背景设置为清晰
  • 将自定义视图的图层类设置为
    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

    }
}

输出:

Result

© www.soinside.com 2019 - 2024. All rights reserved.