什么时候调用layoutSubviews ?

我有一个自定义视图,它在动画期间没有得到layoutSubview消息。

我有一个充满屏幕的视图。它在屏幕底部有一个自定义子视图,如果我改变导航栏的高度,它会在界面生成器中正确地调整大小。layoutSubviews在视图创建时被调用,但不再调用。我的子视图被正确地布局。如果我关闭in-call状态栏,子视图的layoutSubviews将根本不会被调用,即使主视图将其调整为动画。

在什么情况下layoutSubviews会被调用?

我将自定义视图的autoresizesSubviews设置为NO。在界面构建器中,我有顶部和底部的支柱和垂直箭头集。


另一个难题是窗口必须被设置为键:

[window makeKeyAndVisible];

否则子视图不会自动调整大小。

191254 次浏览

你看过layoutIfNeeded吗?

文档片段如下所示。如果在动画期间显式调用此方法,动画是否工作?

< p > layoutIfNeeded 如果需要,显示子视图
- (void)layoutIfNeeded
< p >的讨论 使用此方法在绘制前强制子视图的布局 < p >可用性 支持iPhone OS 2.0及以上版本

我追踪解决方案到Interface Builder的坚持,即不能在已打开模拟屏幕元素(状态栏等)的视图上更改弹簧。由于主视图的弹簧关闭,该视图不能改变大小,因此当in-call栏出现时,该视图将整体向下滚动。

关闭模拟功能,然后调整视图大小并正确设置弹簧,会导致动画发生,并调用我的方法。

在调试这是一个额外的问题,模拟器退出应用程序时,在呼叫状态是通过菜单切换。退出app =没有调试器。

当一个OpenGL应用从SDK 3迁移到SDK 4时,layoutSubviews不再被调用。经过反复试验,我终于打开了主窗口。xib,选择窗口对象,在检查器中选择窗口属性选项卡(最左边),并选中“可见于启动”。似乎在SDK 3中,它仍然用于引起layoutSubViews调用,但在4中没有。

6个小时的挫折终于结束了。

我也有一个类似的问题,但对答案不满意(或者我在网上能找到的任何答案),所以我在实践中尝试了一下,下面是我得到的答案:

  • init不会导致layoutSubviews 被称为(duh)
  • <李> addSubview:原因 函数调用layoutSubviews 视图被添加,视图正在被添加 添加到(目标视图),以及所有 目标的子视图 <李> setFrame视图 智能地调用layoutSubviews on 视图只设置了它的框架 如果帧的size参数为 李不同的< / >
  • 滚动UIScrollView 导致layoutSubviews被调用 scrollView和它的superview
  • 旋转一个设备只调用 layoutSubview在父视图上 响应视图控制器主 李视图)< / >
  • 调整视图的大小会在它的父视图上调用layoutSubviews (重要的是: 如果决定视图大小的内容发生变化,具有固有内容大小的视图将重新调整大小;例如,更新UILabel上的文本将导致内在内容大小被更新,从而在其父视图上调用layoutSubviews)

我的结果- http://blog.logichigh.com/2011/03/16/when-does-layoutsubviews-get-called/

BadPirate的回答中的一些点只部分正确:

  1. 对于addSubView

    addSubview会在被添加的视图、被添加到的视图(目标视图)和目标的所有子视图上调用layoutSubviews。

    它取决于视图(目标视图)的自动调整掩码。如果它有自动调整大小蒙版ON, layoutSubview将在每个addSubview上被调用。如果它没有自动调整大小掩码,那么layoutSubview只会在视图(目标视图)帧大小改变时调用。

    例如:如果你以编程方式创建UIView(默认情况下它没有自动调整大小的掩码),LayoutSubview只会在UIView帧改变时被调用,而不是在每个addSubview上。

    正是通过这种技术,应用程序的性能也提高了

  2. 设备旋转点

    旋转一个设备只调用父视图(响应viewController的主视图)上的layoutSubview。

    只有当你的VC在VC层次结构中(根在window.rootViewController),这才是真的,这是最常见的情况。在iOS 5中,如果你创建了一个VC,但它没有添加到任何其他VC中,那么当设备旋转时,这个VC不会被注意到。因此,调用layoutSubviews将不会注意到它的视图

基于@BadPirate之前的回答,我进行了进一步的尝试,并提出了一些澄清/更正。我发现layoutSubviews:将在视图上被调用当且仅当:

  • 它自己的界限(不是帧)改变了。
  • 它的一个直接子视图的边界改变了。
  • 子视图被添加到视图中或从视图中移除。

一些相关细节:

  • 只有当新值不同时,才会认为边界发生了变化,包括不同的起源。特别注意,这就是为什么每当UIScrollView滚动时都会调用layoutSubviews:,因为它通过改变边界的原点来执行滚动。
  • 改变帧只会在大小改变的情况下改变边界,因为这是唯一传播到bounds属性的东西。
  • 还不在视图层次结构中的视图边界的更改将导致调用layoutSubviews: 当视图最终添加到视图层次结构时
  • 为了完整起见:这些触发器不会直接调用layoutSubviews,而是调用setNeedsLayout,从而设置/引发一个标志。对于所有视图在视图层次结构中,运行循环的每次迭代都会检查这个标志。对于发现该标志被引发的每个视图,将对其调用layoutSubviews:,并重置该标志。层次结构中更高的视图将首先被检查/调用。
< p >调用 [self.view setNeedsLayout]; 在viewController中调用viewDidLayoutSubviews

https://developer.apple.com/library/prerelease/tvos/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/CreatingViews/CreatingViews.html#//apple_ref/doc/uid/TP40009503-CH5-SW1

每当以下任何事件发生时,都会发生布局更改 视图中:

< p >。视图边界矩形的大小改变 b.接口方向发生变化,通常会触发根视图边界矩形的变化 c.与视图的层相关联的核心动画子层的集合改变并需要布局 d.你的应用程序通过调用视图的setNeedsLayoutlayoutIfNeeded方法强制布局发生 e.你的应用程序通过调用视图底层对象的setNeedsLayout方法强制布局

.