如何自动调整从 xib 创建的 MarkerView 的大小
How to automatically resize a MarkerView created from xib
我从 xib 布局创建标记,但它不会根据标签长度调整大小:
我的标记class:
class MyMarker: MarkerView {
@IBOutlet weak var lblValue: UILabel!
override open func awakeFromNib() {
// centering on top of bar
self.offset.x = -self.frame.size.width / 2.0
self.offset.y = -self.frame.size.height - 7.0
}
override func refreshContent(entry: ChartDataEntry, highlight: Highlight) {
lblValue.text = String(entry.y)
}
}
我在 IOS-Charts 库中做了一些挖掘,发现了一个有趣的特性——虽然可以从 xib(其内容是一个视图)创建一个标记,但标记本身并没有添加到查看层次结构。相反,视图的内容只是简单地绘制在图表上 canvas.
如果我们查看 MarkerView
,我们会注意到它只是一个方便的包装器。图表上的渲染发生在 draw(context:point:)
方法中,该方法在 IMarker
协议中定义。即MarkerView
没有添加到视图层级.
在我看来,这可能是 MarkerView
的约束没有重新计算的原因。我试图强制 MarkerView
重新计算它们但没有成功:
override func refreshContent(entry: ChartDataEntry, highlight: Highlight) {
lblValue.text = String(entry.y)
layoutSubviews() // doesn't work
updateConstraints() // doesn't work
subviews.forEach() { // even that doesn't work!
[=11=].updateConstraints()
}
}
我什至尝试调整视图边界的大小(并为清晰起见添加了绿色背景),但这并没有强制重新计算约束:
override func refreshContent(entry: ChartDataEntry, highlight: Highlight) {
lblValue.text = String(entry.y)
bounds = CGRect(x: bounds.minX, y: bounds.minY, width: 200, height: bounds.height)
frame = bounds
backgroundColor = UIColor.green
layoutSubviews() // doesn't work
updateConstraints() // doesn't work
subviews.forEach() { // even that doesn't work!
[=12=].updateConstraints()
}
}
结果:
问题是如何重新计算MarkerView
约束?最重要的是 - 不是手工操作。毕竟,MarkerView
在从 xib 初始化时以某种方式计算出正确的约束。
是的,确实可以重新计算视图常量,即使它不包含在层次结构中。对于 IOS-Charts,它将如下所示:
override func refreshContent(entry: ChartDataEntry, highlight: Highlight) {
lblValue.text = String(entry.y)
// Recalculate marker sized based on lblValue width
setNeedsLayout()
layoutIfNeeded()
// ...
}
我从 xib 布局创建标记,但它不会根据标签长度调整大小:
我的标记class:
class MyMarker: MarkerView {
@IBOutlet weak var lblValue: UILabel!
override open func awakeFromNib() {
// centering on top of bar
self.offset.x = -self.frame.size.width / 2.0
self.offset.y = -self.frame.size.height - 7.0
}
override func refreshContent(entry: ChartDataEntry, highlight: Highlight) {
lblValue.text = String(entry.y)
}
}
我在 IOS-Charts 库中做了一些挖掘,发现了一个有趣的特性——虽然可以从 xib(其内容是一个视图)创建一个标记,但标记本身并没有添加到查看层次结构。相反,视图的内容只是简单地绘制在图表上 canvas.
如果我们查看 MarkerView
,我们会注意到它只是一个方便的包装器。图表上的渲染发生在 draw(context:point:)
方法中,该方法在 IMarker
协议中定义。即MarkerView
没有添加到视图层级.
在我看来,这可能是 MarkerView
的约束没有重新计算的原因。我试图强制 MarkerView
重新计算它们但没有成功:
override func refreshContent(entry: ChartDataEntry, highlight: Highlight) {
lblValue.text = String(entry.y)
layoutSubviews() // doesn't work
updateConstraints() // doesn't work
subviews.forEach() { // even that doesn't work!
[=11=].updateConstraints()
}
}
我什至尝试调整视图边界的大小(并为清晰起见添加了绿色背景),但这并没有强制重新计算约束:
override func refreshContent(entry: ChartDataEntry, highlight: Highlight) {
lblValue.text = String(entry.y)
bounds = CGRect(x: bounds.minX, y: bounds.minY, width: 200, height: bounds.height)
frame = bounds
backgroundColor = UIColor.green
layoutSubviews() // doesn't work
updateConstraints() // doesn't work
subviews.forEach() { // even that doesn't work!
[=12=].updateConstraints()
}
}
结果:
问题是如何重新计算MarkerView
约束?最重要的是 - 不是手工操作。毕竟,MarkerView
在从 xib 初始化时以某种方式计算出正确的约束。
是的,确实可以重新计算视图常量,即使它不包含在层次结构中。对于 IOS-Charts,它将如下所示:
override func refreshContent(entry: ChartDataEntry, highlight: Highlight) {
lblValue.text = String(entry.y)
// Recalculate marker sized based on lblValue width
setNeedsLayout()
layoutIfNeeded()
// ...
}