0

所以我有这样一个嵌套设置的 iPhone 应用程序:[RootViewController]->[UITabBarController]->[UINavigationController]->[subViewControllers]。一切都是以编程方式构建的,而不是在 Interface Builder 中。

我只是想支持所有设备方向。我所有的 AutoResizing 蒙版都已设置好,一切都在必要时旋转和扩展/收缩。除了 NavigationController 的 navBar 和 Toolbar 之外的所有内容。(通常,这些视图会根据方向自动调整大小。即在横向中,导航栏和工具栏应自动调整为大约 32 像素,在纵向模式下为 44 像素。)特殊的是导航控制器的子视图正在调整大小,但是实际的导航栏和工具栏不是。换句话说,内容在任何方向上都会拉伸/收缩大约 12 px 左右,就好像导航栏和工具栏调整了大小一样。这似乎是自动调整大小的面具在做他们的工作。

因此,为了尝试解决这种情况,我为 UINavigationController 创建了一个响应“willRotateToInterfaceOrientation:duration:”的类别,以触发“sizeToFit”选择器。(这项技术来自 Stack Overflow 上的另一篇帖子,也有类似的问题。)在我的研究中,我发现只有最外层的视图控制器会收到此消息,所以我让我的根视图控制器在选项卡控制器上调用它,它反过来在导航控制器等上调用它。这解决了这个问题,现在我的嵌套视图控制器在外部视图旋转时得到通知。使用 sizeToFit 技术,导航栏和工具栏都可以自行调整大小。然而,这仍然留下了重新定位工具栏的问题,以弥补尺寸变化的偏移量。

在 willRotate 方法中执行此操作的棘手之处在于,我们无法知道新的边界视图尺寸是什么,也不知道我们当前的方向是什么。(除非您打开了 deviceOrientationNotifications,但我没有。)我们所要做的就是新的方向是什么,以及我们工具栏的当前帧值是什么。我可以对此进行硬编码并使用一张草稿纸以老式方式计算框架调整,但我真的想保留动态视图大小调整功能,而不会对设备的屏幕尺寸做出任何假设。

因此,使用下面的代码,我设法通过简单地将工具栏相对于它刚刚变成的大小“碰撞”工具栏 12 像素来解决这个问题。为了防止它在用户翻转设备时过度碰撞,我使用当前工具栏的框架高度来导出当前方向。(这意味着我仍然在假设工具栏的大小之前和之后,但我对此感觉更好,因为我可以在一定程度上影响它,而不是尝试以编程方式调整设备的物理屏幕大小。)

@implementation UINavigationController (BLUINavigationControllerAutoRotate)

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
    return TRUE;
}

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];

    // Resize the navBar
    [[self navigationBar] performSelector:@selector(sizeToFit)
                               withObject:nil
                               afterDelay:(0.5f * duration)];

    // Read our current frame size
    CGRect toolbarFrame = self.toolbar.frame;

    // Prevent over adjusting when flipping the device
    if ((toolbarFrame.size.height < 38
         && (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft
             || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight))
        || (toolbarFrame.size.height > 38
            && (toInterfaceOrientation == UIInterfaceOrientationPortrait
                || toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)))
    {
        // We are already resized and repositioned.
        return;
    }

    // Calculate and apply the toolbar offset
    const NSInteger delta = 12;     // the difference in size between 44 and 32 px.
    toolbarFrame.origin.y += ((toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft)
                              || (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)) ? (delta) : (-delta);
    self.toolbar.frame = toolbarFrame;

    // Resize the toolbar
    [[self toolbar] performSelector:@selector(sizeToFit)
                         withObject:nil
                         afterDelay:(0.5f * duration)];

}

@end

所以,现在我已经正确地表现了 NavigationBar 和 Toolbar。最终用户永远不会知道我必须实现所有这些额外的解决方法才能重新启用看起来应该是标准行为的东西。所以我的问题是,为什么我必须做这一切?有没有我应该知道的更好的方法,或者我在其他地方根本没有做的事情?(即 [navigationController setAutomaticallyResizesToolbarOnRotate:TRUE]; 或类似的东西?)就像我说的,这似乎应该是预先连接的,所以我不得不处理转发消息和强制触发器感觉就像一个过度设计的黑客而不是正确的解决方案。

谢谢!

4

1 回答 1

3

您正在将 willRotateToInterfaceOrientation 消息从根视图控制器传递到选项卡视图控制器 - 为什么不传递所有其他旋转消息,看看是否有帮助?IE

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
    [tabBarController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
}

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
    [tabBarController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation  {
    [super didRotateFromInterfaceOrientation:toInterfaceOrientation];
    [tabBarController didRotateFromInterfaceOrientation:toInterfaceOrientation];
}

- (void)willAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
    [tabBarController willAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
}

- (void)didAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    [super didAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation];
    [tabBarController didAnimateFirstHalfOfRotationToInterfaceOrientation:toInterfaceOrientation];
}

- (void)willAnimateSecondHalfOfRotationFromInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willAnimateSecondHalfOfRotationFromInterfaceOrientation:toInterfaceOrientation duration:duration];
    [tabBarController willAnimateSecondHalfOfRotationFromInterfaceOrientation:toInterfaceOrientation duration:duration];
}

如果您将所有这些都传递给标签栏控制器,我很想看看会发生什么 - 您的问题似乎应该自动发生,而不是您所做的所有额外工作!

于 2010-10-03T08:53:07.937 回答