在UINavigationController中的UITableView在旋转后会被覆盖在导航栏下面

3

这是纵向:

alt text

这是横向:

alt text

我已经尝试了旋转,但没有成功:

self.tableView.autoresizesSubviews = YES;
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
8个回答

13

我最近遇到了这个问题。在我的情况下,是因为我对一个不是应用程序窗口根控制器的导航控制器执行了旋转操作。因此,我使用了旋转通知监听器/仿射变换/边界调整方法来更改导航控制器的布局。这个方法可以工作,但会产生这里描述的结果。我花了一段时间才注意到,当我将设备旋转到横屏时,导航栏的高度没有被正确地调整大小(即从44像素到32像素,这是框架在横屏模式下减小的高度)。我的应用程序的根视图控制器已经响应willRotateToInterfaceOrientationdidRotateFromInterfaceOrientation,而且那个视图控制器已经知道关联的导航控制器。我通过将以下代码添加到willRotateToInterfaceOrientation方法中解决了这个问题:

CGRect frame = self.navViewController.navigationBar.frame;
if (toInterfaceOrientation == UIInterfaceOrientationPortrait || toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
    frame.size.height = 44;
} else {
    frame.size.height = 32;
}
self.navViewController.navigationBar.frame = frame;

希望这能在类似情况下为某些人节省时间。


谢谢。不幸的是,在我的情况下,导航栏没有正确地改变高度。似乎当旋转时,正在显示的视图失去了关于导航栏的所有信息,因此它的顶部出现在导航栏下面。当推送并弹出另一个视图时,有问题的视图会被正确重新分配。我尝试了setNeedsLayout,但无效。 - Oscar
1
谢谢,完美地解决了问题。虽然你可以使用(UIInterfaceOrientationIsPortrait(toInterfaceOrientation))代替你的if条件语句,使代码更简洁。或者更好的做法是:frame.size.height = UIInterfaceOrientationIsPortrait(toInterfaceOrientation) ? 44. : 32.; - Ben Baron
首先,这对我有用,但很烦人。其次,我发现将代码放在“willRotate”中比放在“didRotate”中更好(后者似乎会导致视觉跳跃)。第三,我认为在我的情况下会发生这种情况,因为我的根控制器是一个选项卡栏,而单个选项卡具有导航控制器。正如@jstevenco所指出的那样,根控制器正在接收方向调用,而不是nav控制器。我想知道是否有更简洁的方法:让根控制器告诉nav控制器布置其子视图? - coco

7

当使用自定义视图控制器作为根视图控制器时,它需要管理其他视图控制器。因此,它负责将所有旋转事件转发给当前活动的子控制器(如果我可以这么说)。这些事件包括:

 willRotateToInterfaceOrientation:duration:

 willAnimateRotationToInterfaceOrientation:duration:

 didRotateFromInterfaceOrientation:

 willAnimateFirstHalfOfRotationToInterfaceOrientation:duration:

 didAnimateFirstHalfOfRotationToInterfaceOrientation:

 willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:

因此,在由您的自定义根控制器管理的导航控制器的情况下,将 – willAnimateRotationToInterfaceOrientation:duration: 转发到导航控制器可以解决旋转时导航栏高度错误的问题。


2
这是最干净的解决方案。 - Kevin Craft
这应该是被接受的答案。此外,请注意,在iOS 5和6中,您可以自动转发旋转和外观方法。 - Andy

6

在 didRotateFromInterfaceOrientation 方法中添加以下行。

[self.navigationController.view layoutSubviews];

希望这样做就可以了。


2

我有完全相同的问题,@jstevenco 带我找到了一个非常奇怪的解决方案。我的视图在旋转时也会自动调整大小,但是 tableview 似乎不知道导航控制器坐落在哪里:

在 tableviewcontroller 中添加以下内容:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
 CGRect frame = navBar.frame;
if (fromInterfaceOrientation == UIInterfaceOrientationPortrait || fromInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
    frame.size.height = 31.9;
} else {
    frame.size.height = 44.1;
}
navBar.frame = frame;  

}

31.9和44.1非常重要,离开这些是32和44,不需要调整大小,所以它似乎被忽略了。对我有用,希望能帮到其他人。


0

如果您在导航控制器中调用了“willAnimateRotationToInterfaceOrientation:”,但忘记从该方法内部调用super,则可能会出现此问题。

您应该有类似于以下内容:

        - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
        [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation];
// Your code here

    }

如果我添加了那段代码,在编译时会出现以下警告:'UITableViewController' 可能无法响应 '-willAnimateRotationToInterfaceOrientation:' - Jorge
这段代码片段需要放在你的导航控制器中,而不是你的TVC中。 - nzeltzer
如果我添加了那段代码,编译时会收到这个警告:'UIViewController' 可能无法响应 '-willAnimateRotationToInterfaceOrientation:' - Suchita - iOS_User
如果我将此代码放入我的tableViewController或navigationController中,也会收到警告。 - ader

0

不,不是这样的,因为当你向下滑动时,它会再次出现在导航栏下方。在下方还有一个具有相同结果的工具栏。在横屏模式下,tableView 的下部分位于其下方。 - Jorge

0

你的 UINavigationController 需要在设备方向改变时得到通知。如果你只将 UINavigationControllerview 添加到另一个 UIView 中,则不会发生此情况。

从 iOS 5 开始,你可以在父 UIViewController 上简单地调用 addChildViewController:,这将确保方向更改传播到此子视图控制器。


0
在这些情况下需要注意的一件事是,如果您手动更改状态栏,请注意其方向。如果状态栏未隐藏,并且您在状态栏方向错误的情况下更改视图框架(例如,在代码中,您可能正在更新状态栏的方向),即使您没有启用自动调整大小,它也会错误地自动调整导航栏的大小。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接