[英]IntrinsicContentSize on a custom UIView streches the content
我想创建一个使用/提供 IntrinsicContentSize 的自定义UIView
,因为它的高度取决于其内容(就像高度取决于文本的 label 一样)。
虽然我找到了很多关于如何使用现有视图提供的 IntrinsicContentSize 的信息,但我发现了一些关于如何在自定义UIView
上使用 IntrinsicContentSize 的信息:
@IBDesignable class MyIntrinsicView: UIView {
override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
context?.setFillColor(UIColor.gray.cgColor)
context?.fill(CGRect(x: 0, y: 0, width: frame.width, height: 25))
height = 300
invalidateIntrinsicContentSize()
}
@IBInspectable var height: CGFloat = 50
override var intrinsicContentSize: CGSize {
return CGSize(width: super.intrinsicContentSize.width, height: height)
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
invalidateIntrinsicContentSize()
}
}
初始高点设置为50
draw
方法绘制一个大小为25
的灰色矩形
高度更改为300
并调用invalidateIntrinsicContentSize()
在 InterfaceBuilder 中放置一个MyView
实例没有任何问题。 视图不需要高度约束
但是,在 IB 中,使用了50
的初始高度。 为什么? IB 绘制灰色矩形,因此调用draw
方法。 那么为什么高度没有改为300呢?
还有什么奇怪的:当设置背景颜色时,它也被绘制,也没有调用super.draw(...)
。 这是故意的吗?
我期望一个高度为300
的视图和一个高度为25
的灰色矩形。 但是,在模拟器中运行项目时,结果是不同的:
300
- OK似乎内容从其原始高度25
被拉伸以保持其与视图的相对高度。 为什么是这样?
尝试从draw()
内部更改视图的高度可能是一个非常糟糕的主意。
首先,正如您所见,更改内在内容大小不会触发重绘。 其次,如果是这样,您的代码将 go 进入无限递归循环。
看看对 class 的编辑:
@IBDesignable class MyIntrinsicView: UIView {
override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
context?.setFillColor(UIColor.gray.cgColor)
context?.fill(CGRect(x: 0, y: 0, width: frame.width, height: 25))
// probably a really bad idea to do this inside draw()
//height = 300
//invalidateIntrinsicContentSize()
}
@IBInspectable var height: CGFloat = 50 {
didSet {
// call when height var is set
invalidateIntrinsicContentSize()
// we need to trigger draw()
setNeedsDisplay()
}
}
override var intrinsicContentSize: CGSize {
return CGSize(width: super.intrinsicContentSize.width, height: height)
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
// not needed
//invalidateIntrinsicContentSize()
}
}
现在,当您通过IBDesignable
属性更改 IB 中的固有高度时,它将在您的 Storyboard 中正确更新。
下面是在运行时使用它的快速浏览。 每次点击(任何地方)都会将height
属性增加 50 (直到我们超过 300,然后它将被重置为 50),然后使内在内容大小无效并强制调用draw()
:
class QuickTestVC: UIViewController {
@IBOutlet var testView: MyIntrinsicView!
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
var h: CGFloat = testView.intrinsicContentSize.height
h += 50
if h > 300 {
h = 50
}
testView.height = h
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.