在自定义容器视图中旋转时 AutoLayout 不会调整视图大小?

Posted

技术标签:

【中文标题】在自定义容器视图中旋转时 AutoLayout 不会调整视图大小?【英文标题】:AutoLayout won't resize view when rotating in a custom container view? 【发布时间】:2012-11-01 12:38:25 【问题描述】:

我有一个非常基本的容器视图,它包含一个侧边栏并在内容区域中交换视图控制器(想想 UISplitView,但带有一个小图标侧边栏/垂直 UITabBar)。

容器视图控制器使用自动布局并在旋转时正确调整大小。 Content viewController 1 使用自动布局并且是用 IB 制作的,所以它有一个 xib 文件。 Content viewController 2 继承自 UITableViewController,不使用 xib。

如果我将 viewController 1 指定为根视图控制器并旋转,则调整大小会起作用,这是我在 viewController 1 中获得的回调:

willRotateToInterfaceOrientation 更新视图约束 viewWillLayoutSubviews didRotateFromInterfaceOrientation

但是,如果我将容器视图控制器指定为根视图控制器,加载 viewController 1 并旋转,则调整大小不起作用。而且我只在 viewController 1 中得到以下回调:

willRotateToInterfaceOrientation didRotateFromInterfaceOrientation

在我的视图控制器容器中,我是这样交换视图控制器的:

[self addChildViewController:toViewController];
[toViewController didMoveToParentViewController:self];

// Remove the old view controller
[fromViewController willMoveToParentViewController:nil];
[fromViewController.view removeFromSuperview];
[fromViewController removeFromParentViewController];

// Add the new view
[self.contentContainerView addSubview:toViewController.view];

现在,我确实收到了轮换即将发生的回调,但似乎既没有调用 updateViewConstraints 也没有调用 viewWillLayoutSubviews。这解释了为什么没有发生调整大小,但是为什么一旦我将视图控制器放入容器视图中就不会调用这些方法?

我还尝试在我的容器中显式返回 YES

shouldAutomaticallyForwardAppearanceMethods

shouldAutomaticallyForwardAppearanceMethods

虽然这应该已经是默认设置了。

另外,不是用 IB 制作的视图控制器(视图控制器 2)在容器内旋转时会正确调整大小。但是,我没有在这个上明确使用 NSLayoutConstraints,所以我怀疑它默认使用 Springs 和 Struts 来调整旋转时的大小。

我是否需要在我的视图控制器容器上转发一些其他事件以使自动布局视图控制器在旋转时正确调整大小?

【问题讨论】:

【参考方案1】:

好的,我想我的视图控制器容器中缺少这个方法:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
    self.contentViewController.view.frame = self.contentContainerView.bounds;

虽然现在旋转时可以正确调整大小,但它仍然不会触发

updateViewConstraints

在我的子视图控制器中。有趣

【讨论】:

使用一些日志记录,看起来超级视图的方向变化没有传递给孩子。我正在使用情节提要,IB 不允许我更改视图或向顶层视图添加约束。添加这个对我有用: - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration self.view.frame = self.view.superview.bounds; 奇怪,我有一个模态显示的视图控制器,除了这个技巧没有任何效果......确实很有趣。【参考方案2】:

似乎 ios 8 确实为您调用了 updateViewConstraints。但 iOS 7 没有。要在 iOS 7 中调用它,请调用 setNeedsUpdateConstraints,如下所示:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration

    [super willAnimateRotationToInterfaceOrientation:interfaceOrientation duration:duration];

    BOOL isiOS7 = floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1;
    if (isiOS7) 
        // Trigger a call to updateViewConstraints
        [self.view setNeedsUpdateConstraints];
    

在 updateLayoutConstraints 中,检查哪个方向是布局的一个好方法是检查状态栏的方向。这适用于 7 和 8。

UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
BOOL layoutAsLandscape = UIInterfaceOrientationIsLandscape(orientation);

【讨论】:

以上是关于在自定义容器视图中旋转时 AutoLayout 不会调整视图大小?的主要内容,如果未能解决你的问题,请参考以下文章

在自定义视图和视图控制器中使用 AutoLayout

如何借助 AutoLayout 在自定义 UITableviewCell 中添加自定义 UIView(xib)?

AutoLayout - 不旋转的 UIImageView

Xcode Autolayout - 未选中时视图旋转

在自定义容器视图控制器中调用 endEditing 会隐藏键盘但不会更改键盘响应器

在自定义容器控制器中拆分视图控制器?