在iphone官方提供的应用中,有一个计算器应用,竖屏时它是一个简单的计算器;横屏时,它是一个复杂的科学计算器。
从这个计算器应用可以看出,横屏和竖屏时分别采用了不同的视图,而不是同一个视图界面元素的重新布局。这里我们的sample中,竖屏时屏幕中有3个按钮,横屏时屏幕中有4个按钮。
这里我们把创建工程时生成的视图作为竖屏,那么我们需要额外创建一个横屏视图。我们有3种方式来实现横屏视图:
1、创建一个视图的xib文件,并使用Interface Builder涉及这个xib文件,然后从xib文件实例化视图对象。
2、创建一个带xib文件的视图控制器,并使用Interface Builder设计这个xib文件,通过initWithNibName:bundle:构造函数实例化视图控制器,然后通过视图控制器的view属性获得视图对象。
3、创建一个storyboard和一个视图控制器,并使用Interface Builder设计这个storyboard文件,通过storyboard的storyboardWithName:bundle:方法实例化视图控制器,然后通过视图控制器的view属性获得视图对象。
这里我们采用视图控制器和storyboard,内存管理采用ARC。
ViewController.h相关代码:
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (nonatomic,strong) UIView *portraitView;
@property (nonatomic,strong) UIView *landscapeView;
@end
这里我们定义了横屏和竖屏的视图属性。
ViewController.m相关代码:
#import "ViewController.h"
#import "LandscapeViewController.h"
#define deg2rad (M_PI/180)
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
LandscapeViewController *landscapeViewController=[[UIStoryboard storyboardWithName:@"LandscapeStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:@"LandscapeViewController"];
self.landscapeView=landscapeViewController.view;
self.portraitView=self.view;
}
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
if(toInterfaceOrientation==UIDeviceOrientationLandscapeRight){
self.view.transform=CGAffineTransformMakeRotation(deg2rad*(-90.0));
self.view.bounds=CGRectMake(0.0, 20.0, 568.0, 300.0);
}else if(toInterfaceOrientation==UIDeviceOrientationLandscapeLeft){
self.view=self.landscapeView;
self.view.transform=CGAffineTransformMakeRotation(deg2rad*90.0);
self.view.bounds=CGRectMake(0.0, 20.0, 568.0, 300.0);
}else{//portrait
self.view=self.portraitView;
self.view.transform=CGAffineTransformMakeRotation(deg2rad*0.0);
self.view.bounds=CGRectMake(0.0, 20.0, 320.0, 548.0);
}
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
}
在viewDidLoad方法中,我们先获取横屏storyboard,然后再用此对象实例化横屏视图控制器,最后获取横屏视图控制器的view属性值,即横屏view。由于初始界面是竖屏,所以竖屏view就是当前的view。
shouldAutorotate方法用于指定当前视图是否支持旋转。
supportedInterfaceOrientations方法指定视图支持哪个方向的旋转。在iPad中,该方法的返回值默认是UIInterfaceOrientationMaskAll,表示支持所有方向旋转。在iPhone中,其返回值默认是UIInterfaceOrientationMaskAllButUpsideDown,支持除了竖直向下以外的其他3个方向。视图支持某个方向的前提是设备也支持该方向。
willAnimateRotationToInterfaceOrientation:duration:方法在屏幕旋转之前触发,其参数toInterfaceOrientation可以判断屏幕的旋转方向,是枚举UIInterfaceOrientation中定义的常量。UIInterfaceOrientation在UIApplication.h中定义:
// Note that UIInterfaceOrientationLandscapeLeft is equal to UIDeviceOrientationLandscapeRight (and vice versa).
// This is because rotating the device to the left requires rotating the content to the right.
typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {
UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
};
需要注意的是, 在判断向某个方向旋转时,不仅要将旋转的视图替换为当前视图,还要把视图进行旋转变换并重新调整视图的边界。
上述代码中,CGAffineTransformMakeRotation函数是放射变换函数,用于视图的二维坐标变换,类似的还有缩放和位移放射变换函数,其中的参数是弧度。