最后添加一些逻辑,根据设备的方向显示相对应的UIView。UIViewController类中指定的一个任务会在设备旋转后被调用。该任务的名称是didRotateFromInterfaceOrientation:,接收一个表示设备此前所处方向的常量。通过在此任务中添加逻辑,我们可以更新UI来响应方向变化。使用UIDevice类可以知道设备新变化的方向。程序清单2-7显示了我们所需要行为的实现。
程序清单2-7 GameController.m(didRotateFromInterfaceOrientation:)
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)
fromInterfaceOrientation{
UIDevice* device = [UIDevice currentDevice];
[self setOrientation: [device orientation]];
}
-(void)setOrientation:(UIInterfaceOrientation)interfaceOrientation{
if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
interfaceOrientation == UIInterfaceOrientationLandscapeRight){
[portraitView removeFromSuperview];
[self.view addSubview:landscapeView];
[rockPaperScissorsController setup:landscapeHolderView.frame.size];
[landscapeHolderView addSubview:rockPaperScissorsController.view];
} else {
[landscapeView removeFromSuperview];
[self.view addSubview:portraitView];
[rockPaperScissorsController setup:portraitHolderView.frame.size];
[portraitHolderView addSubview:rockPaperScissorsController.view];
}
}
在程序清单2-7中,可以看到该任务接收到的变量为fromInterfaceOrientation,这表示设备旋转前的方向。在应用程序中,我们其实并不会关心设备此前的方向,因此我们从UIDevice类中获取当前设备,并读取其orientation属性,从而获得设备当前(旋转之后)的方向。获得方向后,我们调用setOrientation:方法,程序清单2-7中同样包含该方法。
setOrientation:任务将使用传递的任何方向更新用户界面。如果设备当前是横向,我们将portraitView从其父视图中删除,也就是说,我们把它移出屏幕。然后将视图landscapeView添加到根视图。如果尚未完成子视图的布局,调用rockPaperScissorsController的setup方法使其有机会调整子视图布局。最后将rockPaperScissorsController的view属性以子视图形式添加到landscapeHolder。
之所以将布局逻辑独立成一个单独任务,是因为我们希望在视图控制器首次加载时调用该任务,这样在游戏启动时用户界面就已经被正确设置了。如此一来,我们只需在一个地方放置所有方向处理逻辑即可。
首次运行时,这些对象的状态会有所不同。例如,首次调用该任务时,无论是portraitView还是landscapeView均未被附加到场景中,因此removeFromSubview调用将是一个非操作,不会出错。而后续旋转再次调用此任务时,rockPaperScissorsController的视图已经存在于场景中了,当以子视图方式添加一个视图时,如果已经存在一个子视图,会将其自动从父视图中移除。
事实上,removeFromSuperview和addSubview:具有的这些合理默认行为使得对视图的操作更加便捷。而不必去编写易出错的清理代码。程序清单2-8显示了应用程序初次启动时调用setOrientation:的方式。
程序清单2-8 ViewController.m(viewDidLoad)
- (void)viewDidLoad
{
[super viewDidLoad];
UIDevice* device = [UIDevice currentDevice];
[self setOrientation: [device orientation]];
}
在程序清单2-8中,当ViewController完成初始化并在屏幕上显示时,会调用任务viewDidLoad。在此,我们简单地获取当前设备的方向,并将其数值传递给setOrientation:,以确保在应用程序启动时用户界面的布局方向正确无误。
如果运行此项目,将看到该应用程序在iPad和iPhone上均可运行,并能够根据设备方向调整界面布局。