iOS的横屏(Landscape)与竖屏(Portrait)InterfaceOrientation

0. 应用级别的配置

大家(特指有iOS开发经验的人)应该都知道Xcode Project的工程配置General页签中有那么四个图(或者4个checkbox),标识对四种interfaceOrientation的支持。分别为Portrait、PortraitUpsideDown、LandscapeLeft和LandscapeRight。

对应的,在Xcode Project工程配置的Info页,实际上就是Info.plist中,有对4种Orientation的记录项。

这两者是一样的。

1. Window级别的控制

在iOS6.0之后,UIApplicationDelegate中多了一个方法声明:

1
- ( NSUInteger )application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window

就是对于特定的application和特定的window,我们需要支持哪些interfaceOrientation,这是可以通过实现这个方法定制的。

返回值是一个无符号整数,实际上是可以使用定义好的枚举值:

1
2
3
4
5
6
7
8
9
typedef NS_OPTIONS ( NSUInteger , UIInterfaceOrientationMask) {
     UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
     UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
     UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
     UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
     UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
     UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),
     UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
};

对于UIApplicationDelegate的这个方法声明,大多数情况下application就是当前的application,而window通常也只有一个。所以基本上通过window对横屏竖屏interfaceOrientation的控制相当于全局的。

2. Controller层面的控制

老版本的iOS有这样一个方法:

1
- ( BOOL )shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation NS_DEPRECATED_IOS (2_0, 6_0);

即定制是否可以旋转到特定的interfaceOrientation。

而在iOS6之后,推出了2个新的方法来完成这个任务:

1
2
- ( BOOL )shouldAutorotate NS_AVAILABLE_IOS (6_0);
- ( NSUInteger )supportedInterfaceOrientations NS_AVAILABLE_IOS (6_0);

可以看得出来,两个和在一起就是原来任务的完成过程。其中,大概的判断方式是,先执行前者,判断是否可以旋转,如果为YES,则根据是否支持特定的interfaceOrientation再做决断。

3. 使得特定ViewController坚持特定的interfaceOrientation

iOS6之后还提供了这样一个方法,可以让你的Controller倔强第坚持某个特定的interfaceOrientation:

1
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation NS_AVAILABLE_IOS (6_0);

这就叫坚持,呵呵!
当然,使用这个方法是有前提的,就是当前ViewController是通过全屏的Presentation方式展现出来的。

这里使用的是另外一套枚举量,可以去UIApplication.h中查看定义。

4. 当前屏幕方向interfaceOrientation的获取

有3种方式可以获取到“当前interfaceOrientation”:

  • controller.interfaceOrientation,获取特定controller的方向
  • [[UIApplication sharedApplication] statusBarOrientation] 获取状态条相关的方向
  • [[UIDevice currentDevice] orientation] 获取当前设备的方向

具体区别,可参见StackOverflow的问答:

http://stackoverflow.com/questions/7968451/different-ways-of-getting-current-interface-orientation

5. 容器Controller的支持

上面把interfaceOrientation方向的获取和支持配置都说了,看起来没什么问题了。有没有什么特殊情况?

当你使用TabbarController和NavigationController按照如上做法使用的时候就会有些头疼。

办法不是没有,比较通俗的一种就是——继承实现。

(补充:iOS7之后可以通过delegate对此进行控制)

使用TabbarController和NavigationController后旋转屏幕的解决补充:(继承实现)

首先要子类化UINavigationController,增加下面三个方法

//返回最上层的子Controller的shouldAutorotate 
- (BOOL)shouldAutorotate{     
return self.topViewController.shouldAutorotate; 
}  
//返回最上层的子Controller的supportedInterfaceOrientations 
- (NSUInteger)supportedInterfaceOrientations{     
return self.topViewController.supportedInterfaceOrientations;
 //视图默认显示的方向 -(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {    
 return self.topViewController.preferredInterfaceOrientationForPresentation; 
} 

      子类 RotateNavigationController 代码如下:

 
#import <UIKit/UIKit.h>  
@interface RotateNavigationController : UINavigationController  @end 

  #import "RotateNavigationController.h"   
@implementation RotateNavigationController   
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {     
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];     
if (self) {         
// Custom initialization    
}     
return self; }  
- (void)viewDidLoad {     
[super viewDidLoad];          
}  
- (void)didReceiveMemoryWarning {     
[super didReceiveMemoryWarning];     
}  
//返回最上层的子Controller的shouldAutorotate 
- (BOOL)shouldAutorotate{     
return self.topViewController.shouldAutorotate; 
}  
//返回最上层的子Controller的supportedInterfaceOrientations 
- (NSUInteger)supportedInterfaceOrientations{     
return self.topViewController.supportedInterfaceOrientations; 
}  
//视图默认显示的方向 
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {    
 return self.topViewController.preferredInterfaceOrientationForPresentation;
 }  
@end 

     这三个方法就是用来控制项目中所有的视图页面的横竖屏切换的。这三个方法是系统级的。不需要自己主动去调用,也会运行。

     app启动首先走 main函数,然后main函数调用AppDelegate ,AppDelegate再调用UINavigationController,UINavigationController再调才是你的界面。UINavigationController  继承的也是UIViewController 。但他比UIViewController更进一步。所以我们各个视图的横竖屏控制是由各个控制器来独立控制的,而不再是根控制器。

往后,我们只要在对应的控制器上重写上面的这三个方法即可控制视图的横竖屏。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值