概述:
在iOS6之前的版本中,通常使用 shouldAutorotateToInterfaceOrientation 来单独控制某个UIViewController的方向,需要哪个viewController支持旋转,只需要重写shouldAutorotateToInterfaceOrientation方法。
但是iOS 6里屏幕旋转改变了很多,之前的 shouldAutorotateToInterfaceOrientation 被列为 DEPRECATED 方法,查看UIViewController.h文件也可以看到:
- // Applications should use supportedInterfaceOrientations and/or shouldAutorotate..
- - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation NS_DEPRECATED_IOS(2_0, 6_0);
程序将使用如下2个方法来代替:
- - (BOOL)shouldAutorotate;
- - (NSUInteger)supportedInterfaceOrientations;
除了重写这个2个方法,IOS6里面要旋转还有一些需要注意的地方,下面会细述。另外还有一个硬性条件,需要在Info.plist文件里面添加程序支持的所有方向,可以通过以下2种方式添加
1.
2.
另外要兼容IOS6之前的系统,要保留原来的 shouldAutorotateToInterfaceOrientation 方法,还有那些 willRotateToInterfaceOrientation 等方法。
IOS6自动旋转设置:
- UIViewController *viewCtrl = [[UIViewController alloc] init];
- UINavigationController *navCtrl = [[UINavigationController alloc] initWithRootViewController:viewCtrl];
- if ([window respondsToSelector:@selector(setRootViewController:)]) {
- self.window.rootViewController = navCtrl;
- } else {
- [self.window addSubview:navCtrl.view];
- }
如果需要设置viewCtrl的旋转,那么不能在UIViewController里面重写shouldAutorotate和supportedInterfaceOrientations方法,而是需要在navCtrl里面设置,又因为UINavigationController是系统控件,所以这里需要新建一个UINavigationController的子navigationController的子类,然后在里面实现shouldAutorotate和supportedInterfaceOrientations方法,比如:
- -(NSUInteger)supportedInterfaceOrientations{
- return UIInterfaceOrientationMaskAllButUpsideDown;
- }
- - (BOOL)shouldAutorotate{
- return YES;
- }
还是在navCtrl里面控制,因为viewCtrl和viewCtrl2的rootViewController都是navCtrl,一般的写法都是
- UIViewController *viewCtrl2 = [[UIVewController alloc] init];
- [self.navigationController.navigationController pushViewController:viewCtrl2 animated:YES];
- - (BOOL)shouldAutorotate
- {
- return self.topViewController.shouldAutorotate;
- }
- - (NSUInteger)supportedInterfaceOrientations
- {
- return self.topViewController.supportedInterfaceOrientations;
- }
全部调用self.topViewController,就是返回当前呈现出来的viewController里面的设置,然后在viewCtrl、viewCtrl2等等这些viewController里面重写shouldAutorotate和supportedInterfaceOrientations,以方便设置每个viewController的旋转
eg3:如果viewCtrl 是 presentModalViewController
到 viewCtrl3,那么viewCtrl3的旋转设置就不在navCtrl里面了!如果presentModalViewController的viewController是navController、tabbarController包装过的viewCtrl3,那么就应在新包装的navController、tabbarController里面设置,如果是直接presentModalViewController到viewCtrl3,那么就在viewCtrl3里面设置
方法就行
手动旋转
手动旋转也有2种方式,一种是直接设置 UIDevice 的 orientation,但是这种方式不推荐,上传appStore有被拒的风险:
- if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
- [[UIDevice currentDevice] performSelector:@selector(setOrientation:) withObject:(id)UIInterfaceOrientationPortrait];
- }
第二种是假旋转,并没有改变 UIDevice
的 orientation,而是改变某个view的 transform,利用 CGAffineTransformMakeRotation 来达到目的,比如:
- self.view.transform = CGAffineTransformMakeRotation(M_PI/2)
下面讲解采用第二种方式的各版本手动旋转:
思想是首先设置 statusBarOrientation,然后再改变某个view的方向跟 statusBarOrientation 一致!
IOS6手动旋转:
1. 那既然是旋转,最少也得有2个方向,那么还是少不了上面说的那个硬性条件,先在plist里面设置好所有可能需要旋转的方向。既然是手动旋转,那么就要关闭自动旋转:
- - (BOOL)shouldAutorotate{
- return NO;
- }
2.手动触发某个按钮,调用方法,这个方法的实现如下:
- [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];
- self.view.transform = CGAffineTransformMakeRotation(M_PI/2);
- self.view.bounds = CGRectMake(0, 0, kScreenHeight, 320);
注意:
1. 只需要改变self.view.transform,那么self.view的所有subview都会跟着自动变;其次因为方向变了,所以self.view的大小需要重新设置,不要使用self.view.frame,而是用bounds。
2. 如果shouldAutorotate 返回YES的话,下面设置setStatusBarOrientation 是不管用的!setStatusBarOrientation只有在shouldAutorotate 返回NO的情况下才管用!
IOS5、IOS4手动旋转:
1.在需要手动旋转的viewController里的 shouldAutorotateToInterfaceOrientation 方法设置 interfaceOrientation == [UIApplicationsharedApplication].statusBarOrientation
- - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
- return (interfaceOrientation == [UIApplication sharedApplication].statusBarOrientation);
- }
2.手动触发某个按钮,调用方法,这个方法的实现如下:
- [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];
- self.view.transform = CGAffineTransformMakeRotation(M_PI/2);
- self.view.bounds = CGRectMake(0, 0, kScreenHeight, 320);
注意:只需要改变self.view.transform,那么self.view的所有subview都会跟着自动变;其次因为方向变了,所以self.view的大小需要重新设置,不要使用self.view.frame,而是用bounds。
经验分享:
1.IOS6里面,如果一个项目里面需要各种旋转支持,有自动,有手动,那么我们可以新建2个navController或者tabbarController的子类,一个是不旋转,一个旋转,那么所有需要旋转的UINavigationController都可以用这个子类来代替!包括我们可以定制短信呀、邮件呀的旋转!
2.supportedInterfaceOrientations 方法一般是写UIInterfaceOrientationMask方向,但是如果程序要兼容4.3以下的SDK(4.3以下的SDK必须是4.5以下的Xcode,不支持IOS6),那么在用4.5以下的Xcode编译的时候通不过!所以可以用statusBarOrientation代替或者直接写死数字!
- -(NSUInteger)supportedInterfaceOrientations{
- return [UIApplication sharedApplication].statusBarOrientation;
- }
3.一般都不建议在程序里面直接调用 UIDeviceOrientation 的方向,而是用 UIInterfaceOrientation,他们之间是不同的!
- UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,
- UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
看到吗,左右是反的!Xcode图形化设置方向也是以 UIInterfaceOrientation 为准,就是home按键所在的方向
参考:
http://blog.csdn.net/totogogo/article/details/8002173
http://stackoverflow.com/questions/13200220/how-to-change-keyboard-orientation-in-ios6
http://blog.csdn.net/yiyaaixuexi/article/details/8035014
[self.window addSubview:self.viewController.view];
改为判断当前设备系统
if ([[[UIDevice currentDevice] systemVersion] floatValue]>=4.0) {
//4.0以后支持
self.window.rootViewController = self.viewController;
}
else
[self.window addSubview:self.viewController.view];
2.在viewController.m中重写方法
//ios6以后设备旋转
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
NSLog(@"ios6");
return UIInterfaceOrientationMaskAll;
// self.interfaceOrientation
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
NSLog(@"设备旋转");
}
要翻转的时候,首先响应的方法:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
return YES则支持翻转,NO则不支持。
紧接着
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
被调用。这个方法是发生在翻转开始之前。一般用来禁用某些控件或者停止某些正在进行的活动,比如停止视频播放。
再来是
-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
这个方法发生在翻转的过程中,一般用来定制翻转后各个控件的位置、大小等。可以用另外两个方法来代替:willAnimateFirstHalfOfRotationToInterfaceOrientation:duration: 和 willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:
最后调用的是
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
这个方法发生在整个翻转完成之后。一般用来重新启用某些控件或者继续翻转之前被暂停的活动,比如继续视频播放
3,在info。plist中增加相对应的方向即可
4.获取自身屏幕方法,不要使用[[UIDevice currentDevice] orientation](第一次使用的时候,总是返回0)
而是要使用self.interfaceOrientation或[[UIApplication sharedApplication] statusBarOrientation]
首先,我们必须了解一下下列4种状态,它们被用来描述设备旋转方向:
UIInterfaceOrientationLandscapeLeft |
向左,即HOME键在右 |
UIInterfaceOrientationLandscapeRight |
向右,即HOME键在左 |
UIInterfaceOrientationPortrait |
正立,即HOME键在下 |
UIInterfaceOrientationPortraitUpsideDown |
倒立,即HOME键在上 |
对于旋屏的处理,大致分为如下几种情况和思路:
也许,你不需要旋屏支持,而希望锁定屏幕
1 |
-( BOOL )shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation |
2 |
{ |
3 |
return NO; |
4 |
} |
也许,你需要支持旋屏,或者支持部分方向的旋屏
1 |
-( BOOL )shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { |
2 |
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); |
3 |
} |
也许,你的view有张背景图,旋屏时系统帮助你拉伸了图片,但是却没有管你的其它部件,比如button,你希望直接改变button的大小和位置
01 |
-( void )willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration |
02 |
{ |
03 |
if (UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) { |
04 |
NSLog(@ "现在是竖屏" ); |
05 |
[btn setFrame:CGRectMake(213, 442, 340, 46)]; |
06 |
} |
07 |
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) { |
08 |
NSLog(@ "现在是横屏" ); |
09 |
[btn setFrame:CGRectMake(280, 322, 460, 35)]; |
10 |
} |
11 |
} |
也许,你并不希望用绝对坐标去约束控件,而是希望让它通过旋转自己适应屏幕的旋转
01 |
- ( void )viewDidLoad |
02 |
{ |
03 |
[super viewDidLoad]; |
04 |
// Do any additional setup after loading the view, typically from a nib. |
05 |
UIDevice *device = [UIDevice currentDevice]; |
06 |
[device beginGeneratingDeviceOrientationNotifications]; |
07 |
//利用 NSNotificationCenter 获得旋转信号 UIDeviceOrientationDidChangeNotification |
08 |
NSNotificationCenter *ncenter = [NSNotificationCenter defaultCenter]; |
09 |
[ncenter addObserver:self selector:@selector(orientationChanged) name:UIDeviceOrientationDidChangeNotification object:device]; |
10 |
} |
11 |
12 |
- ( BOOL )shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation |
13 |
{ |
14 |
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); |
15 |
} |
16 |
17 |
-( void )rotation_btn:( float )n |
18 |
{ |
19 |
UIButton *robtn = self.btn; |
20 |
robtn.transform = CGAffineTransformMakeRotation(n*M_PI/180.0); |
21 |
} |
22 |
23 |
-( void )orientationChanged |
24 |
{ |
25 |
UIDeviceOrientation orientaiton = [[UIDevice currentDevice] orientation]; |
26 |
|
27 |
switch (orientaiton) { |
28 |
caseUIDeviceOrientationPortrait: |
29 |
[self rotation_btn:0.0]; |
30 |
break ; |
31 |
caseUIDeviceOrientationPortraitUpsideDown: |
32 |
[self rotation_btn:90.0*2]; |
33 |
break ; |
34 |
caseUIDeviceOrientationLandscapeLeft: |
35 |
[self rotation_btn:90.0*3]; |
36 |
break ; |
37 |
caseUIDeviceOrientationLandscapeRight: |
38 |
[self rotation_btn:90.0]; |
39 |
break ; |
40 |
default : |
41 |
break ; |
42 |
} |
43 |
} |
也许,你需要autoresizesSubviews = YES
也许,你希望横竖屏有不同的布局效果,需要准备2份Subview,在不同状态去替换
当然不要忘记,需要调节设定图示中的1、2处,
转自:http://blog.csdn.net/yiyaaixuexi/article/details/7670852