我有一种情况,我正在使用 UIScrollView 来帮助使用较小手机的用户查看窗口内的全文.如果他们需要滚动,我想显示一个图像图标(只是为了让他们知道窗口内还有更多内容),但我在使用 Swift 查找滚动视图的高度时遇到了问题.
这是我的对象的层次结构
基本上,这 4 个标签适合 4.7 英寸 iPhone,但不适合 4 英寸 iPhone.我尝试设置一些逻辑来检查 UIScrollView 内容是否大于窗口,但它似乎不起作用.我一直认为高度为零.
我正在使用 scrollHeight = scrollView.contentSize.height
并尝试将其放入 viewDidLoad()
、viewWillAppear()
、和 viewDidLayoutSubviews()
但每次它最终都是 0.
contentSize
是我应该用来检查高度的正确方法吗?
TL;DR;
作为一般指南,自动布局不会在调用 viewDidLoad
时完成为视图提供大小(在 viewDidLayoutSubviews
中也不正确).在查询 bounds
或 frame
之前,要确保所有视图及其子视图的大小正确,请执行以下操作:
self.view.setNeedsLayout()self.view.layoutIfNeeded()print(self.someSubview.frame)//给出正确的帧
说明
有点违反直觉,将代码放入 viewDidLayoutSubviews
并不意味着所有子视图都已通过自动布局获得正确的大小.引用
这里是代码:
类 ViewController: UIViewController {@IBOutlet 弱 var childView:UIView!@IBOutlet 弱 var grandchildView:UIView!覆盖 func viewDidLoad() {super.viewDidLoad()print("child", #function, childView.frame.size.width)打印(孙子",#function,grandchildView.frame.size.width)}覆盖 func viewDidLayoutSubviews() {super.viewDidLayoutSubviews()print("child", #function, childView.frame.size.width)打印(孙子",#function,grandchildView.frame.size.width)}覆盖 func viewWillAppear(_ animated: Bool) {super.viewWillAppear(动画)print("child", #function, childView.frame.size.width)打印(孙子",#function,grandchildView.frame.size.width)}覆盖 func viewDidAppear(_ animated: Bool) {super.viewDidAppear(动画)print("child", #function, childView.frame.size.width)打印(孙子",#function,grandchildView.frame.size.width)}}
这是输出:
子 viewDidLoad() 240.0孙子 viewDidLoad() 200.0子视图将出现 240.0孙子 viewWillAppear 200.0child viewDidLayoutSubviews() 271.0//`child` 现在有它的最终宽度孙子 viewDidLayoutSubviews() 200.0//`grandchild` 仍然有它原来的宽度!//现在,在大多数情况下,所有视图都将具有正确的大小.子viewDidAppear 271.0孙子 viewDidAppear 231.0
您可以从此输出中看到,viewDidLayoutSubviews
不保证任何超出视图控制器主视图的直接子视图的内容都具有正确的大小.
注意:通常在调用 viewDidAppear
时,视图具有正确的大小,但我想说这是绝对不能保证.
I have a situation where I'm using a UIScrollView to help users with smaller phones see the full text inside a window. And I was wanting to show an image icon if they needed to scroll (just so that they know there is more inside the window) but I'm having a problem finding the height of the scrollview using Swift.
This is the hierarchy of my objects
Basically, those 4 labels fit inside a 4.7" iPhone but not the 4" iPhone. I tried setting some logic to check if the UIScrollView content is larger than the window, but it doesn't seem to be working. I keep getting that the height is zero.
I'm using scrollHeight = scrollView.contentSize.height
and have tried putting that inside of viewDidLoad()
, viewWillAppear()
, and viewDidLayoutSubviews()
but every time it ends up being 0.
Is contentSize
the right thing I should be using to check the height?
TL;DR;
As a general guide, Auto Layout does not finish giving views their size by the time viewDidLoad
is called (neither is it correct inside viewDidLayoutSubviews
). To make sure all views and their subviews have their correct sizes before querying their bounds
or frame
, do:
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
print(self.someSubview.frame) // gives correct frame
Explanation
Somewhat counterintuitively, putting your code inside viewDidLayoutSubviews
does not mean all sub-views have been given their correct size by Auto Layout. To quote the docs for this method:
However, this method being called does not indicate that the individual layouts of the view's subviews have been adjusted.
What this means is that: inside viewDidLayoutSubviews
, only the first hierarchical-level of sub-views will have their correct size (i.e. child views but not "grandchild views").
Here is an example layout I created (the red view is the child, the blue view is the grandchild).
A few important points about this example:
Note that in Interface Builder, the original width of the child view (red) is 240 points and the original width of the grandchild view (blue) is 200 points.
And here is the code:
class ViewController: UIViewController {
@IBOutlet weak var childView: UIView!
@IBOutlet weak var grandchildView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
print("child ", #function, childView.frame.size.width)
print("grandchild", #function, grandchildView.frame.size.width)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
print("child ", #function, childView.frame.size.width)
print("grandchild", #function, grandchildView.frame.size.width)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
print("child ", #function, childView.frame.size.width)
print("grandchild", #function, grandchildView.frame.size.width)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print("child ", #function, childView.frame.size.width)
print("grandchild", #function, grandchildView.frame.size.width)
}
}
And here is the output:
child viewDidLoad() 240.0
grandchild viewDidLoad() 200.0
child viewWillAppear 240.0
grandchild viewWillAppear 200.0
child viewDidLayoutSubviews() 271.0 // `child` has it's final width now
grandchild viewDidLayoutSubviews() 200.0 // `grandchild` still has it's original width!
// By now, in MOST cases, all views will have their correct sizes.
child viewDidAppear 271.0
grandchild viewDidAppear 231.0
What you can see from this output is that viewDidLayoutSubviews
does not guarantee that anything past the immediate sub-views of the View Controller's principal view have their correct size.
Note: Usually by the time viewDidAppear
is called, views have their correct size, but I'd say this is by no means guaranteed.
这篇关于在Swift中布局后获取UIScrollView的高度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!