Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
734 views
in Technique[技术] by (71.8m points)

ios - Swift: How to subclass CALayer so it resizes automatically?

It is known that the main/root layer of a UIView, e.g., view.layer, will resize automatically to fill the frame of the UIView (however, a root layer's sublayers will not automatically resize).

After subclassing CALayer like:

class CustomLayer : CALayer {
    //...
}

What methods can I implement to "draw" content so that the layer will automatically resize if used as the root CALayer of a view?


The reason I ask this is because I am current calling methods such as:

UIBezierPath(roundedRect: self.view.frame, byRoundingCorners: [.topLeft], cornerRadii: CGSize(width: 17, height: 15))

To update the path of a CALayer, but it would be amazing to be able to create a custom CALayer that can act as a root layer for a UIView so I don't need to consistently update its path.

Does anyone have any advice for this? Ultimately I'm striving to have a layer that can support unique radii for each corner that will automatically fill the UIView and resize without having to consistently update the frame.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You can subclass UIView, override layerClass and return a CAShapeLayer:

class Shape: UIView {

    override public class var layerClass: AnyClass { CAShapeLayer.self }
    var shapeLayer: CAShapeLayer { layer as! CAShapeLayer }
    
    private var bezierPath: UIBezierPath = UIBezierPath() { didSet { shapeLayer.path = bezierPath.cgPath } }
    
    var fillColor: UIColor = .green { didSet { shapeLayer.fillColor = fillColor.cgColor } }
    var strokeColor: UIColor = .blue { didSet { shapeLayer.strokeColor = strokeColor.cgColor } }
    var lineWidth: CGFloat = 2 { didSet { shapeLayer.lineWidth = lineWidth } }
    
    override func didMoveToSuperview() {
        updateShape()
        shapeLayer.fillColor = fillColor.cgColor
        shapeLayer.strokeColor = strokeColor.cgColor
        shapeLayer.lineWidth = lineWidth
    }
    func updateShape() {
        bezierPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: [.topLeft], cornerRadii: CGSize(width: 17, height: 15))
    }
    override func layoutSubviews() {
        super.layoutSubviews()
        print(#function)
        updateShape()
    }
    override public func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        print(#function)
        // you can change the color of your shape here if needed (dark/light mode)
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...