iOS 6:如何将某些视图限制为纵向视图,并允许其他视图旋转?
我有一个iPhone应用程序,它使用一个iOS 6:如何将某些视图限制为纵向视图,并允许其他视图旋转?,ios,iphone,ios6,autorotate,Ios,Iphone,Ios6,Autorotate,我有一个iPhone应用程序,它使用一个UINavigationController来呈现一个深入的界面:首先是一个视图,然后是另一个视图,最多四个层次。我希望前三个视图限制为纵向,并且只允许最后一个视图旋转为横向。当从第四个视图返回到第三个视图时,第四个视图是横向的,我希望所有的东西都旋转回到纵向 在iOS 5中,我只是在每个视图控制器中定义了shouldAutorotateToInterfaceOrientation:,以返回允许方向的YES。所有操作如上所述,包括返回到纵向,即使设备从视图
UINavigationController
来呈现一个深入的界面:首先是一个视图,然后是另一个视图,最多四个层次。我希望前三个视图限制为纵向,并且只允许最后一个视图旋转为横向。当从第四个视图返回到第三个视图时,第四个视图是横向的,我希望所有的东西都旋转回到纵向
在iOS 5中,我只是在每个视图控制器中定义了shouldAutorotateToInterfaceOrientation:
,以返回允许方向的YES。所有操作如上所述,包括返回到纵向,即使设备从视图控制器4返回到3时保持横向
在iOS 6中,所有视图控制器都会旋转到横向,打破了原本不需要的方向。iOS 6发行说明说
更多的责任转移到应用程序和应用程序代表身上。现在,iOS容器(如UINavigationController
)不会咨询其子容器以确定它们是否应该自动旋转。[…]每当设备旋转或每当视图控制器显示为全屏模式显示样式时,系统都会向最顶端的全屏视图控制器(通常为根视图控制器)询问其支持的界面方向。此外,仅当此视图控制器从其shouldAutorotate
方法返回YES时,才会检索支持的方向。[…]系统通过将应用程序的supportedInterfaceOrientionsforWindow:
方法返回的值与最顶端的全屏控制器的supportedInterfaceOrientions
方法返回的值相交来确定是否支持方向
因此,我对UINavigationController
进行了子类化,为我的MainNavigationController
提供了一个布尔属性landscapeOK
,并使用该属性返回支持的接口方向中允许的方向。然后,在我的每个视图控制器的视图中将出现:
方法中,我有这样一行
[(MainNavigationController*)[self navigationController] setLandscapeOK:YES];
告诉myMainNavigationController
所需的行为
问题来了:如果我现在在纵向模式下导航到第四个视图,并将手机翻转过来,它会旋转到横向。现在,我按下后退按钮返回到我的第三个视图,它应该只工作于纵向。但它不会旋转回来。我该怎么做
我试过了
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait]
在我的第三个视图控制器的视图中,将出现方法,但它不起任何作用。这是一个错误的调用方法还是一个错误的调用位置,或者我应该以完全不同的方式实现整个过程?我想对我自己的问题给出一个部分答案。我发现在我的第三个UIViewController
的viewwillbeen
方法中使用的以下代码行可以工作:
[[UIDevice currentDevice]
performSelector:NSSelectorFromString(@"setOrientation:")
withObject:(id)UIInterfaceOrientationPortrait];
但我真的不喜欢这个解决方案。它使用一种技巧来分配只读属性,根据苹果的文档,该属性表示设备的物理方向。这就像告诉iPhone跳转到用户手中的正确方向
我很想把它留在我的应用程序中,因为它很简单。但是感觉不对,所以我想把这个问题留给一个干净的解决方案。请使用以下方法来解决这个问题
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
只返回你想要的方向 我也遇到了同样的问题,找到了适合我的解决方案。
要使其正常工作,仅在UINavigationController中实现支持的接口方向
(NSUInteger)是不够的。
您还需要在您的控制器#3中实现此方法,它是在弹出控制器#4后第一个仅为纵向的方法。
因此,我的UINavigationController中有以下代码:
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
if (self.isLandscapeOK) {
// for iPhone, you could also return UIInterfaceOrientationMaskAllButUpsideDown
return UIInterfaceOrientationMaskAll;
}
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotate {
return [self.viewControllers.lastObject shouldAutorotate];
}
- (NSUInteger)supportedInterfaceOrientations {
return [self.viewControllers.lastObject supportedInterfaceOrientations];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return [self.viewControllers.lastObject shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return [self.viewControllers.lastObject preferredInterfaceOrientationForPresentation];
}
在视图控制器#3中,添加以下内容:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
您不需要向视图控制器1、2和4添加任何内容。
这对我很有用,我希望它能帮助你。添加一个CustomNavigationController
覆盖其中的这些方法:
-(BOOL)shouldAutorotate
{
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}
现在在plist中添加所有方向
在视图控制器中,仅添加所需的:
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
这些方法覆盖导航控制器方法这是我在ios 6.0中用于方向支持的方法
-(BOOL)shouldAutorotate{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskAll;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return UIInterfaceOrientationPortrait;
}
在看了无数类似问题的每个答案之后,没有一个答案对我有用,但它们确实给了我一些想法。以下是我最终解决问题的方式:
首先,确保项目目标中支持的界面方向包含旋转视图所需的所有方向
接下来,对UINavigationController进行分类(因为苹果公司说不要将其子分类):
将您希望能够旋转的类别和视图控制器(我称之为RotatingViewController
)导入到最高级别的视图控制器,该视图控制器应包含导航控制器。在该视图控制器中,实现应自动旋转
,如下所示。请注意,这不应是要旋转的同一视图控制器
-(BOOL)shouldAutorotate {
BOOL shouldRotate = NO;
if ([navigationController.topViewController isMemberOfClass:[RotatingViewController class]] ) {
shouldRotate = [navigationController.topViewController shouldAutorotate];
}
return shouldRotate;
}
最后,在旋转视图控制器
中,实现应自动旋转
和支持的界面方向
,如下所示:
-(BOOL)shouldAutorotate {
// Preparations to rotate view go here
return YES;
}
-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAllButUpsideDown; // or however you want to rotate
}
需要这样做的原因是,iOS 6将旋转控制权交给根视图控制器,而不是俯视图控制器。如果希望单个视图的旋转行为不同于堆栈中的其他视图,则需要在根视图控制器中为其编写一个特定的案例。如果只想强制iOS 6应用程序纵向,则可以添加到以下UIViewController子类中
- (BOOL)shouldAutorotate {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
return YES;
} else {
return NO;
}
}
- (NSUInteger)supportedInterfaceOrientations {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
return UIInterfaceOrientationMaskAll;
} else {
return UIInterfaceOrientationMaskPortrait;
}
}
这可能不适用于所有人,但
[(MainNavigationController*)[self navigationController] setLandscapeOK:YES];
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
self.previousVCLandscapeOK = self.isLandscapeOK; // Store the current VC's orientation preference before pushing on the new VC so we can set this again from within the custom "back" method
self.isLandscapeOK = NO; // Set NO as default for all VC's
if ([viewController isKindOfClass:[YourViewController class]]) {
self.isLandscapeOK = YES;
}
}
if ([viewController isKindOfClass:[ShareViewController class]]) {
UIButton* backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 57, 30)];
[backButton setImage:[UIImage imageNamed:@"back-arrow"] forState:UIControlStateNormal];
[backButton addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem* backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
viewController.navigationItem.leftBarButtonItem = backButtonItem;
UIImageView* shareTitle = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"share-title"]];
[shareTitle setContentMode:UIViewContentModeScaleAspectFit];
[shareTitle setFrame:CGRectMake(0, 0, shareTitle.frame.size.width - 10, shareTitle.frame.size.height - 10)];
viewController.navigationItem.titleView = shareTitle;
} else if(...) {
...
}
- (void)back {
self.isLandscapeOK = self.previousVCLandscapeOK;
self.previousVCLandscapeOK = NO;
[self popViewControllerAnimated:YES];
}
@property (nonatomic) BOOL isLandscapeOK;
@property (nonatomic) BOOL previousVCLandscapeOK;
- (BOOL)shouldAutorotate {
return [self.viewControllers.lastObject shouldAutorotate];
}
- (NSUInteger)supportedInterfaceOrientations {
return [self.viewControllers.lastObject supportedInterfaceOrientations];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return [self.viewControllers.lastObject shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return [self.viewControllers.lastObject preferredInterfaceOrientationForPresentation];
}
-(NSUInteger)supportedInterfaceOrientations
{
UIViewController *topMostViewController = [[Utils getAppDelegate] appNavigationController].topViewController;
if ([topMostViewController isKindOfClass:[SVWebViewController class]]) {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotate {
return [self.selectedViewController shouldAutorotate];
}
- (NSUInteger)supportedInterfaceOrientations {
return [self.selectedViewController supportedInterfaceOrientations];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return [self.selectedViewController shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}
-(BOOL)shouldAutorotate
{
return YES;
}
-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
extension UINavigationController{
override open var shouldAutorotate: Bool {
if topViewController != nil && (topViewController?.isKind(of: LogInViewController.self))!
{
return true
}
return false
}
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if topViewController != nil && (topViewController?.isKind(of: LogInViewController.self))!
{
return .portrait
}
return .landscapeRight
}
override open var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
if topViewController != nil && (topViewController?.isKind(of: LogInViewController.self))!
{
return .portrait
}
return .landscapeRight
}
}
extension UITableViewController {
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if let last = self.navigationController?.childViewControllers.last,
last != self {
return last.supportedInterfaceOrientations
} else {
return [.portrait]
}
}
}
extension MyPreciousViewController {
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return [.portrait,.landscape]
}
}
extension UINavigationController {
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return [.portrait]
}
}
extension UITabBarController {
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return [.portrait]
}
}