繁体   English   中英

在自定义视图中未调用draw(_ rect:CGRect)

[英]draw(_ rect: CGRect) not getting called in custom view

我试图通过扩展类UIView来创建自定义视图,该类可以在自定义视图的中心显示一个圆圈。 为了添加自定义图形,我重写了draw(_ rect:CGRect)方法,如下所示。

    public override func draw(_ rect: CGRect) {
        super.draw(rect)
        let center = CGPoint(x: bounds.width / 2, y: bounds.height / 2)
        let minLength = bounds.width <= bounds.height ? bounds.width : bounds.height
        let circlePath = UIBezierPath (arcCenter: center, radius: CGFloat(minLength  / 2), startAngle: 0, endAngle: CGFloat(Float(360).degreesToRadians) , clockwise: true)

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = circlePath.cgPath
        shapeLayer.fillColor = circleColor.cgColor
        layer.addSublayer(shapeLayer)
    }

但是,当我尝试在情节提要中添加相同的自定义组件并在draw方法中添加断点时,它没有被调用。 出于好奇,我在要调用的init?(coder aDecoder:NSCoder)方法中添加了一个断点。 另外,当我尝试覆盖以下方法时,它工作正常。

required public init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    drawCircle()
}

fileprivate func drawCircle() {
    let center = CGPoint(x: bounds.width / 2, y: bounds.height / 2)
    let minLength = bounds.width <= bounds.height ? bounds.width : bounds.height
    let circlePath = UIBezierPath (arcCenter: center, radius: CGFloat(minLength  / 2), startAngle: 0, endAngle: CGFloat(Float(360).degreesToRadians) , clockwise: true)

    let shapeLayer = CAShapeLayer()
    shapeLayer.path = circlePath.cgPath
    shapeLayer.fillColor = circleColor.cgColor

    layer.addSublayer(shapeLayer)
}

方法的问题是我有一个自定义属性circleColor

@IBInspectable
public var circleColor : UIColor = UIColor.gray

调用init方法时尚未设置,并且始终绘制一个灰色圆圈。

请帮助使我知道未调用draw方法的原因。

提前致谢

我不确定您的根本错误在哪里,但您不应仅为了添加层而重写draw(:) 这意味着每次组件重新渲染时都会再次添加一个新层。 那不是你想要的。

更改color属性时,还应确保更新了图层颜色。 为此,只需保存对图层的引用:

private let shapeLayer = CAShapeLayer()

@IBInspectable
public var circleColor : UIColor = UIColor.gray  {
   didSet {
      shapeLayer.fillColor = circleColor.cgColor
   }
}

public override init(frame: CGRect = .zero) {
    super.init(frame: frame)
    updateLayer()
    layer.addSublayer(shapeLayer)
}

required public init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    updateLayer()
    layer.addSublayer(shapeLayer)
}

fileprivate func updateLayer() {
    let center = CGPoint(x: bounds.width / 2, y: bounds.height / 2)
    let minLength = min(bounds.width, bounds.height)
    let circlePath = UIBezierPath(arcCenter: center, radius: minLength / 2, startAngle: 0, endAngle: CGFloat(Float(360).degreesToRadians), clockwise: true)

    shapeLayer.path = circlePath.cgPath
    shapeLayer.fillColor = circleColor.cgColor
}

override func layoutSubviews() {
    super.layoutSubviews()
    // update layer position
    updateLayer()
}

如果您确实想覆盖draw(rect:) ,则根本不需要创建层或覆盖初始化器:

@IBInspectable
public var circleColor : UIColor = UIColor.gray  {
   didSet {
      setNeedsDisplay()
   }
}

public override func draw(_ rect: CGRect) {
    // no need to call super.draw(rect)

    let center = CGPoint(x: bounds.width / 2, y: bounds.height / 2)
    let minLength = min(bounds.width, bounds.height)
    let circlePath = UIBezierPath(arcCenter: center, radius: minLength / 2, startAngle: 0, endAngle: .pi * 2, clockwise: true)

    // the following methods use current CGContext
    circleColor.set()
    circlePath.fill()
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM