Restrict/Force 使用 UITabBarController 时只有一些视图控制器指向特定方向 and/or UINavigationController
Restrict/Force only some view controllers to specific orientations when using UITabBarController and/or UINavigationController
我在网上到处搜索,但找不到关于此的明确答案。当一个 UIViewController
嵌入 UINavigationController
中时,只有一个 UIViewController
支持横向模式的最佳方法是什么?UINavigationController
大多数解决方案,like this one,建议覆盖
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
在AppDelegate
。这有点工作,但是当从唯一支持横向模式的 ViewController
返回时,所有其他(非横向 ViewControllers)也将处于横向。他们不保持纵向。
我已经看到应用程序可以做到这一点,所以我知道这一定是可行的。例如,电影播放器应用程序通常是纵向的,但实际的电影播放器视图是在强制横向模式下模态呈现的。关闭模态 viewcontroller 后,底层 viewcontroller 仍然正确地处于纵向,
有什么提示吗?
你应该把上面的代码写到UINavigationController
子类中。您应该使用 if 语句定义您的应用程序方向并分离您的视图控制器方向。
-(BOOL)shouldAutorotate {
if ([[self.viewControllers lastObject] isKindOfClass:[UIViewController class]] ) {
return [[self.viewControllers lastObject] shouldAutorotate];
}
return NO;
}
- (NSUInteger)supportedInterfaceOrientations {
if ([[self.viewControllers lastObject] isKindOfClass:[UIViewController class]]) {
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
这是我经过 大量 研究后得出的结论:
首先,我尝试实施
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window;
在 AppDelegate 中,如 here 所述,适用于大多数情况。但是除了感觉相当 "hacky" 之外,还有一个严重的问题:模态显示视图控制器的解决方法(参见 "A small problem with modal controllers" 部分)在例如显示 AVPlayerViewController
时失效,因为它实现了它自己的 dismiss 方法,你不能挂钩它来设置 self.isPresented
(不幸的是,viewWillDisappear:
来不及了)。
所以我采用了另一种方法,将 sub类 用于 UITabBarController
和 UINavigationController
,感觉更简洁,只是稍微冗长一点:
CustomNavigationController
CustomNavigationController.h
#import <UIKit/UIKit.h>
@interface CustomNavigationController : UINavigationController
@end
CustomNavigationController.m
#import "CustomNavigationController.h"
@implementation CustomNavigationController
- (BOOL)shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}
- (NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [self.topViewController preferredInterfaceOrientationForPresentation];
}
@end
CustomTabBarController
CustomTabBarController.h
#import <UIKit/UIKit.h>
@interface CustomTabBarController : UITabBarController
@end
CustomTabBarController.m
#import "CustomTabBarController.h"
@implementation CustomTabBarController
- (BOOL)shouldAutorotate
{
return [self.selectedViewController shouldAutorotate];
}
- (NSUInteger)supportedInterfaceOrientations
{
return [self.selectedViewController supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}
@end
之后只需将以下代码添加到您的 UIViewControllers
:
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
// Presents the `UIViewController` in landscape orientation when it is first displayed
return UIInterfaceOrientationLandscapeLeft;
}
- (NSUInteger)supportedInterfaceOrientations {
// Allows all other orientations (except upside-down)
return UIInterfaceOrientationMaskAllButUpsideDown;
}
现在您可以在每个视图控制器的基础上决定首选和支持的方向。请注意,我没有在我的视图控制器中实现 shouldAutorotate
因为它默认为 YES,如果你的视图控制器应该被强制到某个方向(是的,它们应该自动旋转到唯一支持的方向),这就是你想要的.
调用链是这样的:
CustomTabBarController
,即 window 的 rootViewController
,被要求supported/preferred 方向
CustomTabBarController
依次询问它的selectedViewController
(当前选中的tab的view controller),正好是我的CustomNavigationController
CustomNavigationController
询问嵌入的topViewController
,这最终是实际UIViewController
实现上述方法
您仍然需要在构建目标中允许所有设备方向。当然,您需要更新 storyboards/xibs/classes 以使用这些子 类 而不是标准 UINavigationController
和 UITabBarController
类.
这种方法的唯一缺点是,至少在我的情况下,我必须将这些方法添加到我的视图控制器的 所有 中,以使大多数视图控制器仅显示纵向和一些景观能力。但恕我直言,这绝对值得!
我在网上到处搜索,但找不到关于此的明确答案。当一个 UIViewController
嵌入 UINavigationController
中时,只有一个 UIViewController
支持横向模式的最佳方法是什么?UINavigationController
大多数解决方案,like this one,建议覆盖
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
在AppDelegate
。这有点工作,但是当从唯一支持横向模式的 ViewController
返回时,所有其他(非横向 ViewControllers)也将处于横向。他们不保持纵向。
我已经看到应用程序可以做到这一点,所以我知道这一定是可行的。例如,电影播放器应用程序通常是纵向的,但实际的电影播放器视图是在强制横向模式下模态呈现的。关闭模态 viewcontroller 后,底层 viewcontroller 仍然正确地处于纵向,
有什么提示吗?
你应该把上面的代码写到UINavigationController
子类中。您应该使用 if 语句定义您的应用程序方向并分离您的视图控制器方向。
-(BOOL)shouldAutorotate {
if ([[self.viewControllers lastObject] isKindOfClass:[UIViewController class]] ) {
return [[self.viewControllers lastObject] shouldAutorotate];
}
return NO;
}
- (NSUInteger)supportedInterfaceOrientations {
if ([[self.viewControllers lastObject] isKindOfClass:[UIViewController class]]) {
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
这是我经过 大量 研究后得出的结论:
首先,我尝试实施
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window;
在 AppDelegate 中,如 here 所述,适用于大多数情况。但是除了感觉相当 "hacky" 之外,还有一个严重的问题:模态显示视图控制器的解决方法(参见 "A small problem with modal controllers" 部分)在例如显示 AVPlayerViewController
时失效,因为它实现了它自己的 dismiss 方法,你不能挂钩它来设置 self.isPresented
(不幸的是,viewWillDisappear:
来不及了)。
所以我采用了另一种方法,将 sub类 用于 UITabBarController
和 UINavigationController
,感觉更简洁,只是稍微冗长一点:
CustomNavigationController
CustomNavigationController.h
#import <UIKit/UIKit.h>
@interface CustomNavigationController : UINavigationController
@end
CustomNavigationController.m
#import "CustomNavigationController.h"
@implementation CustomNavigationController
- (BOOL)shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}
- (NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [self.topViewController preferredInterfaceOrientationForPresentation];
}
@end
CustomTabBarController
CustomTabBarController.h
#import <UIKit/UIKit.h>
@interface CustomTabBarController : UITabBarController
@end
CustomTabBarController.m
#import "CustomTabBarController.h"
@implementation CustomTabBarController
- (BOOL)shouldAutorotate
{
return [self.selectedViewController shouldAutorotate];
}
- (NSUInteger)supportedInterfaceOrientations
{
return [self.selectedViewController supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}
@end
之后只需将以下代码添加到您的 UIViewControllers
:
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
// Presents the `UIViewController` in landscape orientation when it is first displayed
return UIInterfaceOrientationLandscapeLeft;
}
- (NSUInteger)supportedInterfaceOrientations {
// Allows all other orientations (except upside-down)
return UIInterfaceOrientationMaskAllButUpsideDown;
}
现在您可以在每个视图控制器的基础上决定首选和支持的方向。请注意,我没有在我的视图控制器中实现 shouldAutorotate
因为它默认为 YES,如果你的视图控制器应该被强制到某个方向(是的,它们应该自动旋转到唯一支持的方向),这就是你想要的.
调用链是这样的:
CustomTabBarController
,即 window 的rootViewController
,被要求supported/preferred 方向CustomTabBarController
依次询问它的selectedViewController
(当前选中的tab的view controller),正好是我的CustomNavigationController
CustomNavigationController
询问嵌入的topViewController
,这最终是实际UIViewController
实现上述方法
您仍然需要在构建目标中允许所有设备方向。当然,您需要更新 storyboards/xibs/classes 以使用这些子 类 而不是标准 UINavigationController
和 UITabBarController
类.
这种方法的唯一缺点是,至少在我的情况下,我必须将这些方法添加到我的视图控制器的 所有 中,以使大多数视图控制器仅显示纵向和一些景观能力。但恕我直言,这绝对值得!