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

Joe*_*rea 5 iphone rotation uitabbarcontroller uiscrollview uinavigationcontroller

问候!这是场景.

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

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

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
Run Code Online (Sandbox Code Playgroud)

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

现在,我已经阅读了有关UINavigationController和autorotation的帖子,我怀疑我正在以错误的方式解决这个问题,并且让它变得更加复杂.

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

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

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

Jes*_*ark 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
Run Code Online (Sandbox Code Playgroud)

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


Joe*_*rea 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类.

现在我们开始营业了.只需将其添加到新的VC源:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES; // Adjust to taste
}
Run Code Online (Sandbox Code Playgroud)

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

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

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {   
    return [self.selectedViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}
Run Code Online (Sandbox Code Playgroud)

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

return (interfaceOrientation == UIInterfaceOrientationPortrait);
Run Code Online (Sandbox Code Playgroud)

然而,同样的VC可以将用户带到照相馆,为此,我希望允许一些旋转.在VC的自动旋转方法中,我的反应不同:

return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
Run Code Online (Sandbox Code Playgroud)

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