【iOS】本体の回転にあわせて、TabBarを回転させずにTabBarItemだけを回転させる
こんにちは、andyです。
今回はGPUImage関連がちょっとネタ切れになったので、全く別のことを書きたいと思います。
いま、カメラ機能を持ったアプリを作っているのですが、カメラって本体を回転させたときにカメラの映像を表示しているViewは回転させたくないけど、画面内のGUIは本体の回転に合わせて回転させたい要素があるなんてことがあったので、ちょっと調べてみました。
iOS7のカメラアプリでは、本体を回転させるとメニューバーは回転しませんが、ボタンは回転します。
このような状態を作りたかったので、TabBarを用意して、そこに2つのViewControllerを接続し、片方のViewControllerではTabBar Itemを回転させ、もう片方では回転させない様にしてみました。
下準備
まず、Xcodeのプロジェクト設定のGeneralを表示します。この中で、Deployment Info>Device Orientationを次の様に設定します。
次に、StoryboardでTabBarControllerと、そこに接続された2つのViewControllerを作ります。
コード
この2つのViewControllerの内の1つを次のコードを実装したViewControllerにします。コードはこんな感じ。
@interface CustomRotationViewController () @end @implementation CustomRotationViewController - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewDidAppear:(BOOL)animated { //解説-1 [self rotateGUI:[UIDevice currentDevice].orientation]; //解説-2 [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didDeviceRotated:) name:UIDeviceOrientationDidChangeNotification object:nil]; } - (void)viewWillDisappear:(BOOL)animated { //解説-3 [[NSNotificationCenter defaultCenter] removeObserver:self]; [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; //解説-4 [self correspondToDeviceRotation:0]; } - (void)didDeviceRotated:(NSNotification*)notification { //解説-5 UIDeviceOrientation orient = [(UIDevice*)[notification object] orientation]; [self rotateGUI:orient]; } //解説-6 - (void)rotateGUI:(UIDeviceOrientation)orient { switch (orient) { case UIDeviceOrientationPortrait: NSLog(@"ポートレイト"); [self correspondToDeviceRotation:0]; break; case UIDeviceOrientationPortraitUpsideDown: NSLog(@"ポートレイト逆向き"); [self correspondToDeviceRotation:180]; break; case UIDeviceOrientationLandscapeLeft: NSLog(@"ランドスケープ左向き"); [self correspondToDeviceRotation:90]; break; case UIDeviceOrientationLandscapeRight: NSLog(@"ランドスケープ右向き"); [self correspondToDeviceRotation:270]; break; case UIDeviceOrientationFaceUp: NSLog(@"画面上向き"); break; case UIDeviceOrientationFaceDown: NSLog(@"画面下向き"); break; default: NSLog(@"向き不明"); break; } } //解説-7 - (void)correspondToDeviceRotation:(int)angle { CGAffineTransform t = CGAffineTransformMakeRotation(angle * M_PI / 180); [UIView beginAnimations:@"device rotation" context:nil]; [UIView setAnimationDuration:0.3]; UITabBarController* tabBarController = (UITabBarController*)self.parentViewController; NSArray* tabBarItems = tabBarController.tabBar.items; for (UITabBarItem* item in tabBarItems) { UIView *view = [item valueForKey:@"view"]; view.transform = t; } [UIView commitAnimations]; } @end
解説
それではコードの解説です。
解説-1
このViewControllerのViewが表示された時点で、デバイスのオリエンテーションを取得してrotateGUIメソッドを呼び出しています。rotateGUIメソッドは、GUIを個別に回転させるためのメソッドです。
解説-2
DeviceOrientationNotificationsの取得を開始しています。また、UIDeviceOrientationDidChangeNotificationが発生した際にdidDeviceRotatedメソッドを呼び出すようにオブザーバに登録しています。
解説-3
このViewControllerのViewが非表示になった時点で、解説-2で登録したオブザーバを破棄し、DeviceOrientationNotificationsの取得を終了しています。
解説-4
このViewControllerのViewが非表示になった時点(別のViewControllerに移動した)で、GUIの回転を元に戻しています。
解説-5
引数でもらったNotificationからデバイスのオリエンテーションを取得し、rotateGUIメソッドに渡しています。
解説-6
引数でもらったデバイスのオリエンテーションを元に、GUIの回転角度を設定し、correspondToDeviceRotationメソッドへ回転角度を渡しています。
解説-7
引数からGUIを回転させるためのCGAffineTransformを作成し、各アイテムに回転アニメーションを設定しています。
これで、このViewControllerが表示されているときだけTabBar Itemがデバイスのオリエンテーションにあわせて回転します。
余り使わないかもしれませんが、GUIのデザイン上TabBarごと回転されると困るときなどに使えると思います。
今回はこれで終わり。
次回はどうするか決めてません。アプリを作っていく段階で必要になったことを書いていこうと思います。
それでは。
コメントをどうぞ