我有一个自定义视图,在动画期间没有收到layoutSubview
条消息。
我有一个填充屏幕的视图。如果我更改导航栏的高度,它在屏幕底部有一个自定义子视图,可以在Interface Builder中正确调整大小。创建视图时会调用layoutSubviews
,但不会再次调用layoutSubviews
。我的子视图已正确布局。如果我关闭通话中状态栏,则根本不会调用子视图的layoutSubviews
,即使主视图确实为其调整大小设置了动画。
在什么情况下实际调用autoresizesSubviews
?
我的自定义视图设置为NO
[window makeKeyAndVisible];
。在Interface Builder中,我有顶部和底部支柱以及垂直箭头设置。
难题的另一部分是必须使窗口成为关键:
{{1}}
其他子视图不会自动调整大小。
答案 0 :(得分:466)
我有一个类似的问题,但是对答案不满意(或者我在网上找到的任何答案),所以我在实践中尝试过,这就是我得到的:
init
不会导致layoutSubviews
被称为(duh)addSubview:
原因
layoutSubviews
被召唤
视图被添加,它正在视图
添加到(目标视图),以及所有
目标的子视图setFrame
智能地调用layoutSubviews
视图仅设置框架
如果框架的尺寸参数是
不同layoutSubviews
被调用
scrollView及其superview layoutSubview
(
响应viewControllers主要
视图)layoutSubviews
我的结果 - http://blog.logichigh.com/2011/03/16/when-does-layoutsubviews-get-called/
答案 1 :(得分:72)
在@BadPirate的前一个答案的基础上,我进行了一些实验,并提出了一些澄清/更正。我发现只有在以下情况下才会在视图上调用layoutSubviews:
一些相关细节:
layoutSubviews:
的原因,因为它通过更改其边界的原点来执行滚动。layoutSubviews:
。setNeedsLayout
,它设置/引发一个标志。对于视图层次结构中的所有视图,运行循环的每次迭代都会检查此标志。对于发现标记的每个视图,在其上调用layoutSubviews:
并重置标志。将首先检查/调用层次结构中较高的视图。答案 2 :(得分:16)
只要发生以下任何事件,就会发生布局更改 在一个视图中:
一个。视图边界矩形的大小会发生变化 湾发生界面方向更改,通常会触发根视图边界矩形的更改 C。与视图图层关联的Core Animation子图层集会发生变化并需要布局 d。您的应用程序通过调用视图的
setNeedsLayout
或layoutIfNeeded
方法来强制进行布局 即您的应用程序通过调用视图的基础图层对象的setNeedsLayout
方法来强制布局。
答案 3 :(得分:9)
BadPirate's answer中的一些要点只是部分正确:
addSubView
点
addSubview
导致在要添加的视图,要添加到的视图(目标视图)以及目标的所有子视图上调用layoutSubviews。
取决于视图的(目标视图)自动调整大小。如果它具有自动调整大小掩码ON,则将在每个addSubview
上调用layoutSubview。如果它没有自动调整大小掩码,则只有在视图(目标视图)帧大小发生变化时才会调用layoutSubview。
示例:如果您以编程方式创建了UIView(默认情况下它没有自动调整大小),只有当UIView帧不在每个addSubview
上发生更改时,才会调用LayoutSubview。
通过这种技术,应用程序的性能也会提高。
对于设备旋转点
旋转设备只调用父视图上的layoutSubview(响应的viewController的主视图)
仅当您的VC位于VC层次结构(window.rootViewController
中的根目录)时才会出现这种情况,这是最常见的情况。在iOS 5中,如果您创建了一个VC,但它没有被添加到任何其他VC中,那么当设备旋转时,此VC就不会被注意到。因此,调用layoutSubviews不会引起注意。
答案 4 :(得分:7)
我将解决方案跟踪到Interface Builder的坚持,即在打开模拟屏幕元素的视图(状态栏等)上无法更改弹簧。由于弹簧在主视图中关闭,因此该视图无法改变大小,因此当呼叫栏出现时,该视图完全向下滚动。
关闭模拟功能,然后调整视图大小并正确设置弹簧会导致动画发生并调用我的方法。
调试时的一个额外问题是,当通过菜单切换通话中状态时,模拟器退出应用程序。退出app = no debugger。
答案 5 :(得分:7)
主叫
[self.view setNeedsLayout];
在viewController中使它调用viewDidLayoutSubviews
答案 6 :(得分:4)
文档摘要如下。如果在动画期间显式调用此方法,动画是否有效?
layoutIfNeeded 如果需要,可以布置子视图。
- (void)layoutIfNeeded
讨论 使用此方法在绘制之前强制子视图的布局。
状况 适用于iPhone OS 2.0及更高版本。
答案 7 :(得分:2)
将OpenGL应用程序从SDK 3迁移到4时,不再调用layoutSubviews。经过大量的反复试验后,我终于打开了MainWindow.xib,选中了Window对象,在检查器中选择了Window Attributes选项卡(最左边)并选中了“在启动时可见”。似乎在SDK 3中它仍然用于引起layoutSubViews调用,但不是4。
结束了6个小时的挫折。
答案 8 :(得分:0)
layoutSubviews
永远不会被调用时,一个相当模糊但又可能很重要的案例是:
import UIKit
class View: UIView {
override class var layerClass: AnyClass { return Layer.self }
class Layer: CALayer {
override func layoutSublayers() {
// if we don't call super.layoutSublayers()...
print(type(of: self), #function)
}
}
override func layoutSubviews() {
// ... this method never gets called by the OS!
print(type(of: self), #function)
}
}
let view = View(frame: CGRect(x: 0, y: 0, width: 100, height: 100))