我创建了一个自定义的UILabel
子类,该子类的中间有一个圆圈,标签的文本(是一个数字)将位于圆圈的顶部。
起初我想使用layer.cornerRadius
来做到这一点,但是当标签的宽度和高度不相等时,这不会产生一个圆。
我的意思是,对于宽度为100,高度为50的标签,我仍然想要一个半径为50,中心为(50,25)的圆。
因此,我尝试使用UIBezierPath
画圆。这是我尝试过的:
override func draw(_ rect: CGRect) {
super.draw(rect)
if bounds.height > bounds.width {
let y = (bounds.height - bounds.width) / 2
let path = UIBezierPath(ovalIn: CGRect(x: 0, y: y, width: bounds.width, height: bounds.width))
circleColor.setFill()
path.fill()
} else {
let x = (bounds.width - bounds.height) / 2
let path = UIBezierPath(ovalIn: CGRect(x: x, y: 0, width: bounds.height, height: bounds.height))
circleColor.setFill()
path.fill()
}
}
我放置super.draw(rect)
是因为我认为这样会绘制标签的文本,但是当我运行应用程序时,我只会看到圆圈而不是标签文本。
我很困惑,因为为什么super.draw(rect)
没有绘制标签的文本?
答案 0 :(得分:3)
之所以看不到该文本,是因为UIBezierPath
的“ z-index”取决于它们的绘制顺序。换句话说,UIBezierPath
是彼此重叠绘制的。
super.draw(rect)
确实绘制了文本。但是,当您将其作为第一条语句时,它将首先绘制 ,因此之后绘制的所有内容都将放在文本的顶部。要解决此问题,您应该最后拨打super.draw(rect)
:
override func draw(_ rect: CGRect) {
if bounds.height > bounds.width {
let y = (bounds.height - bounds.width) / 2
let path = UIBezierPath(ovalIn: CGRect(x: 0, y: y, width: bounds.width, height: bounds.width))
circleColor.setFill()
path.fill()
} else {
let x = (bounds.width - bounds.height) / 2
let path = UIBezierPath(ovalIn: CGRect(x: x, y: 0, width: bounds.height, height: bounds.height))
circleColor.setFill()
path.fill()
}
super.draw(rect) // <------- here!
}
或者,仅继承UIView
,在draw(_:)
中绘制圆圈,然后添加UILabel
作为其子视图。这种方法的优点是它不依赖于super.draw(_:)
的实现,将来可能会发生变化,