お使いのブラウザは、バージョンが古すぎます。

このサイトは、Internet Explore8・Internet Explore9には対応しておりません。
恐れ入りますが、お使いのブラウザをバージョンアップしていただきますよう宜しくお願いいたします。

【iOS】本体の回転にあわせて、TabBarを回転させずにTabBarItemだけを回転させる

こんにちは、andyです。
今回はGPUImage関連がちょっとネタ切れになったので、全く別のことを書きたいと思います。

いま、カメラ機能を持ったアプリを作っているのですが、カメラって本体を回転させたときにカメラの映像を表示しているViewは回転させたくないけど、画面内のGUIは本体の回転に合わせて回転させたい要素があるなんてことがあったので、ちょっと調べてみました。


iOS7のカメラアプリでは、本体を回転させるとメニューバーは回転しませんが、ボタンは回転します。
このような状態を作りたかったので、TabBarを用意して、そこに2つのViewControllerを接続し、片方のViewControllerではTabBar Itemを回転させ、もう片方では回転させない様にしてみました。

下準備

まず、Xcodeのプロジェクト設定のGeneralを表示します。この中で、Deployment Info>Device Orientationを次の様に設定します。
device


次に、StoryboardでTabBarControllerと、そこに接続された2つのViewControllerを作ります。
storyboard

コード

この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ごと回転されると困るときなどに使えると思います。


今回はこれで終わり。
次回はどうするか決めてません。アプリを作っていく段階で必要になったことを書いていこうと思います。


それでは。

コメントをどうぞ

メールアドレスは公開されません。* が付いている欄は必須項目です。


お気軽にお問い合わせください。

日本VTR実験室では、お仕事のご依頼、ブログ・コラムのご感想などを受け付けております。
アプリ開発・コンテンツ制作でお困りでしたら、お気軽にご相談ください。
ご連絡お待ちしております。

お問い合わせはこちらから

03-3541-1230

info@nvtrlab.jp

電話受付対応時間:平日AM9:30〜PM6:00