在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函数是放射变换函数,用于视图的二维坐标变换,类似的还有缩放和位移放射变换函数,其中的参数是弧度。