[英]IntrinsicContentSize on a custom UIView streches the content
I would like to create a custom UIView
which uses/offers a IntrinsicContentSize, since its height depends on its content (just like a label where the height depends on the text).我想创建一个使用/提供 IntrinsicContentSize 的自定义
UIView
,因为它的高度取决于其内容(就像高度取决于文本的 label 一样)。
While I found a lot of information on how to work with IntrinsicContentSize offered by existing Views, I found just a few bits on how to use IntrinsicContentSize on a custom UIView
:虽然我找到了很多关于如何使用现有视图提供的 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()
}
}
The initial high is set to 50
初始高点设置为
50
The draw
methods draws a gray rect with a size 25
draw
方法绘制一个大小为25
的灰色矩形
height is changed to 300
and invalidateIntrinsicContentSize()
is called高度更改为
300
并调用invalidateIntrinsicContentSize()
Placing a MyView
instance in InterfaceBuilder works without any problem.在 InterfaceBuilder 中放置一个
MyView
实例没有任何问题。 The view does not need a height constraint视图不需要高度约束
However, in IB the initial height of 50
is used.但是,在 IB 中,使用了
50
的初始高度。 Why?为什么? IB draws the gray rect, thus the
draw
method is called. IB 绘制灰色矩形,因此调用
draw
方法。 So why is the height not changed to 300?那么为什么高度没有改为300呢?
What is also strange: When setting a background color it is drawn as well, also super.draw(...)
is not called.还有什么奇怪的:当设置背景颜色时,它也被绘制,也没有调用
super.draw(...)
。 Is this intended?这是故意的吗?
I would expect a view with height of 300
and a gray rect at the top with a height of 25
.我期望一个高度为
300
的视图和一个高度为25
的灰色矩形。 However, when running the project in simulator the result is different:但是,在模拟器中运行项目时,结果是不同的:
300
- OK300
- OKIt seems that the content was stretched from its original height of 25
to keep its relative height to the view.似乎内容从其原始高度
25
被拉伸以保持其与视图的相对高度。 Why is this?为什么是这样?
Trying to change the view's height from inside draw()
is probably a really bad idea.尝试从
draw()
内部更改视图的高度可能是一个非常糟糕的主意。
First, as you've seen, changing the intrinsic content size does not trigger a redraw.首先,正如您所见,更改内在内容大小不会触发重绘。 Second, if it did, your code would go into an infinite recursion loop.
其次,如果是这样,您的代码将 go 进入无限递归循环。
Take a look at this edit to your class:看看对 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()
}
}
Now, when you change the intrinsic height in IB via the IBDesignable
property, it will update in your Storyboard properly.现在,当您通过
IBDesignable
属性更改 IB 中的固有高度时,它将在您的 Storyboard 中正确更新。
Here's a quick look at using it at run-time.下面是在运行时使用它的快速浏览。 Each tap (anywhere) will increase the
height
property by 50 (until we get over 300, when it will be reset to 50), which then invalidates the intrinsic content size and forces a call to draw()
:每次点击(任何地方)都会将
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.