选项卡控制器和导航控制器在横屏模式下的使用,第二部分

6
我有一个UITabBarController,每个选项卡都处理不同的UIViewController,并根据需要在堆栈上推送新控制器。在其中两个选项卡中,当达到特定控制器时,我需要能够旋转iPhone并以横向模式可视化视图。经过很多努力,我发现必须子类化UITabBarController以覆盖shouldAutorotateToInterfaceOrientation。然而,如果我只是在实现中返回YES,则会出现以下不良副作用:
当旋转iPhone时,每个选项卡中的每个控制器都会自动进入横向模式。
即使在每个控制器中覆盖shouldAutorotateToInterfaceOrientation并返回NO也无效:当旋转iPhone时,控制器仍会进入横向模式。
我在子类化的UITabBarController中实现了shouldAutorotateToInterfaceOrientation如下:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    if([self selectedIndex] == 0 || [self selectedIndex] == 3)
        return YES;

    return NO;
}

我希望只有我感兴趣的两个选项卡能够支持横屏模式。是否有一种方法可以为特定选项卡堆栈上的特定控制器支持横屏模式?

我尝试过以下操作,但没有成功:

(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

if([self selectedIndex] == 0 || [self selectedIndex] == 3)
{   
   if ([[self selectedViewController] isKindOfClass: [landscapeModeViewController class]])
           return YES;
    }

     return NO;

此外,我尝试使用委托方法didSelectViewController,但没有成功。非常感谢您的帮助。谢谢。

7个回答

7

这是一个对UITabBarController的扩展,它将shouldAutorotateToInterfaceOrientation的调用委托给当前选定的子控制器。使用这个扩展,您不再需要子类化UITabBarController,您可以像预期的那样在控制器中使用shouldAutorotateToInterfaceOrientation

UITabBarController+Autorotate.h:

#import <UIKit/UIKit.h>

@interface UITabBarController (Autorotate)
@end

UITabBarController+Autorotate.m:

#import "UITabBarController+Autorotate.h"

@implementation UITabBarController (Autorotate)

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

@end

1
实际上这甚至不是必要的。UITabBarController似乎做了类似的事情,但只同意每个选项卡的每个控制器支持的方向。 - Zargony
Andreas,那将是绝妙的消息!但我在我的应用程序中没有看到那个。在我的情况下,除非我将请求移到视图控制器,否则旋转请求永远不会到达。一旦我把它放进去,标签栏控制器就会被首先调用,然后我就能够传播到VC。如果我漏掉了什么,请指教!实际上,当VC位于选项卡栏的“更多”部分时,我仍然遇到麻烦。在这种情况下,甚至都没有调用标签栏控制器。 :( - Joe D'Andrea
我已经在新的帖子中发布了我的传奇。http://is.gd/2emkj(重定向回stackoverflow.com) - Joe D'Andrea

4
这对我有用:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    if(self.selectedIndex == 0 && [[[self.viewControllers objectAtIndex:0] visibleViewController] isKindOfClass:[MyViewController class]])
        return YES;
    else
        return NO;
}

Rich,非常感谢。提出的解决方案非常好用;-) 这个问题让我疯了!我没有意识到正确的方法还需要同时检查visibleViewController。很棒的答案! - Massimo Cafaro

3

我一直以来都能够在我的应用程序的选项卡控制器中使用它,而且没有出现任何问题:

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

这样,在适当的 VC 中,我们就可以进行 真正的 检查,例如针对照片库视图(还有什么?):

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

我的画廊视图甚至不在给定导航控制器的堆栈顶部。它仍然被调用。

然而,我刚刚发现当VC潜伏在MoreViewController中时,这种方法并不奏效(与四个主要选项卡不同)。在这种情况下,我的画廊VC永远不会被调用。我认为这是因为我一直在调用的VC实际上是所选选项卡的导航控制器,然后将事物传播到适当的VC,在这种情况下是我的照片画廊VC。但对于More VC,情况并不那么顺利...然后事情就会出现问题。: \

我尝试使用Andreas的修改(请参见本线程中的其他位置),但无济于事。欢迎提供线索!


啊哈!当我尝试旋转界面时,只有在使用More View Controller中的VC时,我才会在控制台日志中看到这个:“使用两阶段旋转动画。为了使用更平滑的单阶段动画,该应用程序必须删除两阶段方法实现。”嗯...新闻快报,我没有使用两阶段动画!也就是说,我根本没有响应willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:。显然More视图控制器正在使用它,因此我永远不会收到willAnimateRotationToInterfaceOrientation:duration:的调用...:( - Joe D'Andrea
事实上,如果我试图寻找SecondHalf版本...我也没有收到那个电话。嗯... - Joe D'Andrea

2

当我使用UITabBarController时,遇到了与您相同的问题。我需要控制哪些UIViewController可以旋转,哪些不能。我的主要问题是MORE选项卡。我不希望MORE选项卡中包含的任何UIViewController旋转。

我的解决方案是创建自己的UITabBarController,我称之为MyTabBarController:

@interface MyTabBarController : UITabBarController <UITabBarDelegate> {

}

然后我实现了shouldAutorotateToInterfaceOrientation方法:

@implementation MyTabBarController

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
 UIViewController *controller = [self selectedViewController];

 if ((controller == [self moreNavigationController]) || ([self selectedIndex] == 4))
 {
  return interfaceOrientation == UIInterfaceOrientationPortrait;
 }

 return [controller shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}

@end

我需要确定MORE选项卡是否被选中。这是一个两步过程;当最初选择MORE选项卡时,API返回的selectedIndex大于4,因此我需要将所选控制器与moreNavigationController进行比较。
如果从MORE选项卡中选择了UIViewController,则selectedIndex最终为4,但selectedController不再是moreNavigationController,而是所选的UIViewController。
if ((controller == [self moreNavigationController]) || ([self selectedIndex] == 4))解决了这个问题。
现在,当我运行我的应用程序时,MORE选项卡中的UIViewControllers不会旋转。我希望这能帮助其他遇到同样问题的开发人员。
Emilio

谢谢。我不得不实现这个方法,因为我在程序中以编程方式创建了我的tabbarcontroller,似乎它找不到shouldAutorotateToInterfaceOrientation方法,即使它在同一个视图控制器或应用程序委托中定义。我必须这样做来支持iOS5上的方向更改,但在iOS6上不是必需的。 - estemendoza

1

从我在这里和其他地方看到的,我拼凑出了一个解决方案,使用了方法shouldAutorotate,因为旧的shouldAutorotateToInterfaceOrientation已被弃用。

我把它放在了UITabBarController的一个类别中。我非常希望这是可以接受的!

// call to method shouldAutorotate replaces call to method shouldAutorotateToInterfaceOrientation (deprecated)
-(BOOL)shouldAutorotate
{ // check whether selected view controller should autorotate    
  UIViewController *controller = self.selectedViewController;
  if ([controller isKindOfClass:[UINavigationController class]])
    { // in case it is a navigation controller: get visible view of that
      controller = [(UINavigationController *)controller visibleViewController];
    }
  return [controller shouldAutorotate];
}

0

谢谢,谢谢,谢谢。这花了我两天时间才弄明白如何做到这一点。以下是我对于当您拥有一个带有navigationControllers的tabBarController时所有伟大帮助的看法。

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

UIViewController *controller = self.selectedViewController;
if ([controller isKindOfClass:[UINavigationController class]])
    controller = [(UINavigationController *)controller visibleViewController];

if([controller isKindOfClass:[LOCviewcontroller class]])
    return YES;
else
    if([controller isKindOfClass:[personWebSiteView class]])
        return YES;
else return NO; 

}

任何对新手程序员代码的批评都是受欢迎的...杰克


0

在上面被接受的答案中,子类化UITabBarController真的可以吗?

我理解苹果公司说过“你永远不应该子类化UITabBarController或UINavigationController”之类的话 - 或者我误解了吗?

无论如何,我找到了这个教程,他们在其中子类化了一个UIViewController,并将UITabBarController放入其中。


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