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

发布于 2024-07-29 23:08:43 字数 1192 浏览 3 评论 0原文

问候! 这是场景。

从导航控制器开始(并且不存在选项卡栏 - 它在之前的视图控制器推送中被隐藏),我初始化一个新的视图控制器并将其推送到导航控制器堆栈上。 这个新的 VC 包含一个孤独的 UIView,我以编程方式向其中添加一个具有相同框架的 UIScrollView。 (我想避免 UIView,但这是我可以将 self.view 分配给某些东西的唯一方法。我怀疑投射 UIScrollViewviewDidLoad 中的 UIView 。)

所以现在我们有一个导航栏和一个滚动视图。 我已经将其设置为滚动浏览一些图像(我知道,这是很大的惊喜!),效果很好。 现在我希望它支持自动旋转。 所以我在VC中这样回应:

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

编译并运行。 啊啊……没什么。 显然我做错了什么。

现在,我已经阅读了有关 UINavigationController 和自动旋转 的帖子,我隐隐怀疑我我正在以错误的方式处理这件事,并使事情变得比必要的更加复杂。

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

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

我敢尝试使用模态 VC 吗? (是的 - 不,这也不对。而且它还有一个导航栏。)

Greetings! Here's the scenario.

Starting with a navigation controller (and no tab bar is present - it is hidden from a previous view controller push), I init a new view controller and push it onto the nav controller stack. This new VC contains a lonesome UIView into which I programmatically add a UIScrollView with the same frame. (I wanted to avoid the UIView, but this was the only way I could get self.view to be assigned to something. I suspect casting a UIScrollView to UIView in viewDidLoad is not advisable.)

So now we have a nav bar, and a scroll view. I've set it up to scroll through some images (big surprise, I know!), and that works just fine. Now I want this to support autorotation. So I respond in the VC like so:

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

Compile and run. Aaaand ... nothing. Obviously I've done something wrong.

Now, I've already read the post regarding UINavigationController and autorotation, and I get the sneaking suspicion that I'm going about this the wrong way, and making it way more complicated than necessary.

There's got to be a better way to present a UIScrollView that supports autorotation. Perhaps the Nav Controller is getting in the way, but I'm not sure how to get around it.

Ideally, I'd like something without any kind of nav bar showing. Instead, we have a toolbar/status bar that appears/hides from the top (like you see when playing video). If the nav bar must remain - or if that's REALLY a shorter-height nav bar I'm seeing when playing video vs. a toolbar, however do I get the thing to rotate around? The thing is, I only want it to rotate in this particular mode, when viewing the pix. Not at any other time.

Dare I try using a modal VC? (Yeccch - no, that can't be right either. Plus it has a nav bar anyway.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦魇绽荼蘼 2024-08-05 23:08:48

它还可以更简单:

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

2)更改您的xxxAppDelegate.h< /code> 将 UITabBarController 的类更改为您刚刚创建的子类。 (使用 #import YourNewTabBarController.h)

3) 在 MainWindow.xib 中,将选项卡栏控制器的类更改为您的新类。

急!

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

It can be simpler still:

1) Subclass UITabBarController and implement the shouldAutorotate... as you described (second code snippet)

2) Change your xxxAppDelegate.h to have the class of the UITabBarController changed to the subclass you just created. (use #import YourNewTabBarController.h)

3) In MainWindow.xib change the class of the tab bar controller to your new class.

Presto!

PS: YourNewTabBarController should ONLY implement the shouldAutoRotate....
Remove all other (auto generated) stuff.

若言繁花未落 2024-08-05 23:08:47

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

确实,没有标签栏可见……但这仍然是一个基于标签栏的应用程序的核心。

除非UITabBarController允许自动旋转,否则任何其他视图都将被取消。 因此,只需子类化 UITabBarController 并适当响应 shouldAutorotateToInterfaceOrientation: (而不是像 Xcode 默认情况下将其作为 App Delegate 的一部分)。

你是怎样做的? 很高兴你问了。 仅当您使用 Xcode 默认值创建了选项卡栏控制器应用程序时,才需要执行这些步骤。 (尝试此操作之前请备份您的工作!免责声明,yadda yadda。)

  1. 创建一个新的 UIViewController 子类(我们将其称为 VC)。 将其调整为具有 UITabBarControllerDelegate 显式委托的 UITabBarController 子类。
  2. 将应用程序委托中的所有选项卡栏委托位移植到这个新的 VC 中。
  3. 在新 VC 的 viewDidLoad 方法中,将 self.delegate = self; 添加到末尾。
  4. MainWindow.xib 中(或定义标签栏控制器和标签栏的任何位置),选择标签栏控制器对象并转到身份检查器 (Cmd-4)。 将类更改为新的 VC,而不是标准的 UITabBarController 类。

现在我们开始做生意了。 只需将其添加到新的 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 响应相同的方法,并且它将冒泡到选项卡栏控制器! 例如,在我的应用中,我有一个 VC,我只想以肖像方式显示,因此我的响应如下:

return (interfaceOrientation == UIInterfaceOrientationPortrait);

但是,同一个 VC 可以将用户带到照片库,为此我这样做 想要允许一些轮换。 在该 VC 的自动旋转方法中,我的反应不同:

return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);

现在图库视图将允许自动旋转到除颠倒纵向之外的所有方向,而且当我返回视图控制器链时,方向将恢复为纵向。 :)

Yep - it was easier than I thought!

True, no tab bar is visible ... but this is still, at the core, a tab bar-based app.

Unless the UITabBarController allows autorotation, all bets are off for any other views. So, it's simply a matter of subclassing UITabBarController and responding appropriately to shouldAutorotateToInterfaceOrientation: (vs. making it part of the App Delegate as Xcode does by default).

How do you do that? Glad you asked. Follow these steps only if you've created a tab bar controller app using the Xcode defaults. (BACKUP your work before trying this! Disclaimer disclaimer, yadda yadda.)

  1. Create a new UIViewController subclass (we'll call it VC). Adjust it to be a subclass of a UITabBarController with an explicit delegate of UITabBarControllerDelegate.
  2. Transplant all the Tab Bar delegate bits from your App Delegate into this new VC.
  3. In your new VC's viewDidLoad method, add self.delegate = self; to the end.
  4. In MainWindow.xib (or wherever your tab bar controller and tab bar are defined), pick your Tab Bar Controller object and go to the Identity Inspector (Cmd-4). Change the class to your new VC instead of the standard UITabBarController class.

Now we're in business. Just add this to the new VC source:

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

Why the delegate stuff? The IB file's owner is UIApplication, and I couldn't tie the delegate to my new VC via IB. Since I want the chance to respond to delegate methods, I added it in explicitly. If you don't need that, it's OK to leave it out. (If this can be done in IB, someone please chime in!)

The only remaining trick is setting this to YES selectively. You may not want to support autorotation all of the time (as is my case). Here's how I do it. First, I change that newly-added method (from above) ... to this:

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

Now I can respond to this same method from any of my app's VCs, and it will bubble up to the Tab Bar controller! For instance, in my app, I have a VC that I only want to show in Portrait, so I respond like so:

return (interfaceOrientation == UIInterfaceOrientationPortrait);

However, this same VC can take the user to a photo gallery, for which I do want to allow some rotation. In that VC's autorotate method, I respond differently:

return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);

Now the gallery view will allow autorotation to all orientations except upside-down portrait, plus when I go back up the view controller chain, the orientation reverts to portrait. :)

夜灵血窟げ 2024-08-05 23:08:46

您可以通过创建 UITabBarController 类别来解决此问题,而无需子类化。

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

@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。

You can solve this without subclassing by creating a UITabBarController category.

Here is the category implementation which handles my case where I have anonymous UINavigationControllers associated with my tabs and custom UIViewController subclasses as the root view controllers of the 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

I also have a category on UINavigationController which defaults to returning YES. So, the default behavior is to enable rotation and I can return NO from shouldAutorotateToInterfaceOrientation:interfaceOrientation for just the controllers and orientations for which I wish to disable rotation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文