UINavigationController和UITabBarController中的选择性自动旋转

时间:2009-07-28 21:10:13

标签: iphone uinavigationcontroller uiscrollview uitabbarcontroller rotation

问候!这是场景。

从导航控制器开始(并且没有标签栏 - 它在以前的视图控制器推送中隐藏),我启动一个新的视图控制器并将其推送到导航控制器堆栈。这个新VC包含一个寂寞的 UIView ,我在其中以编程方式添加具有相同帧的UIScrollView。 (我想避免使用 UIView ,但这是我可以将 self.view 分配给某些东西的唯一方法。我怀疑是否会投出 UIScrollView viewDidLoad 中使用strong> to UIView 。)

所以现在我们有一个导航栏和一个滚动视图。我把它设置为滚动浏览一些图像(大惊喜,我知道!),这很好用。现在我希望这支持自动旋转。所以我在VC中回应如下:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

编译并运行。 Aaaand ......没什么。显然我做错了。

现在,我已经阅读了有关UINavigationController and autorotation的帖子,我怀疑我会以错误的方式解决这个问题,并使其变得比必要的更复杂。

必须有一种更好的方式来呈现支持自动旋转的 UIScrollView 。也许导航控制器正在阻碍,但我不知道如何解决它。

理想情况下,我想要一些没有任何导航条显示的东西。相反,我们有一个工具栏/状态栏,从顶部显示/隐藏(就像你在播放视频时看到的那样)。如果导航栏必须保留 - 或者如果真的是一个较短高度的导航栏,我在播放视频与工具栏时会看到,但是我是否可以旋转?问题是,我只希望它在查看像素时以这种特定模式旋转。不是在任何其他时间。

我敢尝试使用模态VC吗? (Yeccch - 不,那也不对。加上它还有一个导航栏。)

3 个答案:

答案 0 :(得分:13)

您可以通过创建UITabBarController类别来解决此问题而不进行子类化。

这是处理我的情况的类别实现,其中我有与我的选项卡关联的匿名UINavigationControllers和自定义UIViewController子类作为UINavigationControllers的根视图控制器:

@implementation UITabBarController (Rotation)

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{   
    if ([self.selectedViewController isKindOfClass:[UINavigationController class]]) {
        UIViewController *rootController = [((UINavigationController *)self.selectedViewController).viewControllers objectAtIndex:0];
        return [rootController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
    }
    return [self.selectedViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}

@end

我在UINavigationController上也有一个类别,默认返回YES。因此,默认行为是启用旋转,我可以从shouldAutorotateToInterfaceOrientation:interfaceOrientation返回NO,仅用于我希望禁用旋转的控制器和方向。

答案 1 :(得分:5)

是的 - 它比我想象的更容易

是的,没有标签栏可见......但这仍然是基于标签栏的应用程序。

除非 UITabBarController 允许自动旋转,否则所有其他观看的所有投注均已关闭。因此,只需要对 UITabBarController 进行子类化并适当地响应shouldAutorotateToInterfaceOrientation:(默认情况下将其作为X代码执行的App Delegate的一部分)。

你是怎么做到的?很高兴你问。仅当您使用Xcode默认值创建了标签栏控制器应用程序时,才按照以下步骤操作。 (备份你的工作在尝试之前!免责声明免责声明,yadda yadda。)

  1. 创建一个新的 UIViewController 子类(我们称之为VC)。将其调整为 UITabBarController 的子类,并使用UITabBarControllerDelegate的显式委托。
  2. 将App Delegate中的所有Tab Bar委托位移植到此新VC中。
  3. 在新VC的viewDidLoad方法中,将self.delegate = self;添加到最后。
  4. MainWindow.xib (或定义了标签栏控制器和标签栏的任何位置)中,选择Tab Bar Controller对象并转到Identity Inspector( Cmd-4 )。将类更改为新的VC而不是标准的 UITabBarController 类。
  5. 现在我们正在开展业务。只需将其添加到新的VC源:

    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
        return YES; // Adjust to taste
    }
    

    为什么代表的东西? IB文件的所有者是 UIApplication ,我无法通过IB将代表绑定到我的新VC。由于我希望有机会响应委托方法,因此我明确地添加了它。如果您不需要,可以将其删除。 (如果可以在IB中完成,有人请加入!)

    唯一剩下的技巧是将其设置为YES 有选择地。你可能不想一直支持自转(就我的情况而言)。这是我如何做到的。首先,我将新添加的方法(从上面)改为......:

    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {   
        return [self.selectedViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
    }
    

    现在我可以从我的任何应用程序的VC中回复相同的方法,它会冒泡到Tab Bar控制器!例如,在我的应用程序中,我有一个我只想在Portrait中显示的VC,所以我这样回答:

    return (interfaceOrientation == UIInterfaceOrientationPortrait);
    

    然而,这个相同的VC可以将用户带到照片库,我希望允许一些旋转。在VC的自转方法中,我的反应不同:

    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
    

    现在画廊视图将允许自动旋转到除了颠倒的肖像之外的所有方向,再加上当我返回视图控制器链时,方向将恢复为纵向。 :)

答案 2 :(得分:1)

它可以更简单:

1)子类UITabBarController并实施shouldAutorotate ...如您所述(第二个代码段)

2)更改您的xxxAppDelegate.h,让UITabBarController的班级更改为您刚刚创建的子类。 (使用#import YourNewTabBarController.h)

3)在MainWindow.xib中将标签栏控制器的类更改为新类。

的Presto!

PS:YourNewTabBarController应该只执行shouldAutoRotate .... 删除所有其他(自动生成的)内容。