Ios 绘图(rect:CGRect)未在自定义视图中调用
我试图通过扩展UIView类来创建自定义视图,UIView类可以在自定义视图的中心显示一个圆。 为了添加自定义图形,我覆盖draw_rect:CGRect方法,如下所示Ios 绘图(rect:CGRect)未在自定义视图中调用,ios,swift,Ios,Swift,我试图通过扩展UIView类来创建自定义视图,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 minLengt
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)
}
当调用init方法时,它还没有被设置,并且它总是画一个灰色的圆圈
请帮助我了解未调用draw方法的原因
提前感谢我不确定您的根本错误在哪里,但您不应该覆盖draw:只是为了添加一个层。这意味着每次组件重新渲染时都会再次添加一个新层。那不是你想要的 还应确保在更改“颜色”特性时更新图层颜色。为此,只需将引用保存到图层:
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()
}
如果确实要覆盖drawrect:,则根本不需要创建图层或覆盖初始值设定项:
@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()
}
顺便说一下,您可以使用let minLength=minbounds.width,bounds.height,如果degressToRadians实现正确,那么使用CGFloat360.DegreesToradians就足够了。注意,在draw中添加子层不是一个好主意。子层只能添加一次,而不是每次重新渲染时。还请注意,您必须在需要时更新层的框架。还请注意,您应该始终实现所有指定的初始值设定项,而不仅仅是initcoder:,initframe:也必须实现。@Sulthan point注意到。也会发生同样的变化。谢谢你的建议。不过,我的问题是,调用重写的draw方法的最低标准是什么。我遗漏了什么吗?每次需要重新提交组件时,即调用setNeedsDisplay时,都应该调用重写的方法。它应该至少被调用一次。奇怪的是,它根本没有被调用。当然,视图必须被添加到superview中,并且具有非零大小。
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()
}
@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()
}