iPhoneアプリでデバイスの回転を独自に対応する

こんにちは、@yoheiMuneです。
今日は、iPhone/iPadアプリケーションで、デバイスの回転に独自に対応する方法を学んだので、ブログに残しておきたいと思います。



まずはデバイスの回転を感知して、必要に応じて各種アイテムを回転させる

バイス回転を独自に感知するには、UIDeviceクラスとNSNotificationCenterクラスを利用します。詳しい利用方法は、"iPhoneの向きを特定するもう一つの方法"を参考にしてみて下さい。
バイスが回転したら、特定のメソッドが呼び出されるように設定します。

// ViewControllerの実装にて
- (void)viewDidLoad {
  [super viewDidLoad];

  // デバイスの回転を開始する
  [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
  // デバイスが回転した際に、呼び出してほしいメソッドを設定する。
  // 今回は、selfのdidRotate:というメソッドを呼び出し対象に設定してみました。
  [[NSNotificationCenter defaultCenter] addObserver:self 
                                                         selector:@selector(didRotate:) 
                                                             name:UIDeviceOrientationDidChangeNotification 
                                                            object:nil];
}

バイスが回転したら、以下のメソッドが呼び出されます。
このメソッドの中で、デバイスの向きに合わせて画面上のアイテムを回転します。
また、ステータスバーの位置も修正します。

// デバイスが回転した際に、呼び出されるメソッド
- (void) didRotate:(NSNotification *)notification {
  UIDeviceOrientation o = [[notification object] orientation];

  // 縦向きで、ホームボタンが下になる向き
  if (o == UIDeviceOrientationPortrait) {

    // 画面上の各種アイテムを回転させる為に作ったメソッド。内容は下を参照ください。
    [self correspondToDeviceRotation:0];
    // ステータスバーの位置を変更する。
    [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationPortrait animated:YES];

  // 縦向きで、ホームボタンが上になる向き
  } else if (o == UIDeviceOrientationPortraitUpsideDown) {
    [self correspondToDeviceRotation:180];
    [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationPortraitUpsideDown animated:YES];

  // 横向きで、ホームボタンが右になる向き		
  } else if (o == UIDeviceOrientationLandscapeLeft) {
    [self correspondToDeviceRotation:90];
    [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:YES];

  // 横向きで、ホームボタンが左になる向き
  } else if (o == UIDeviceOrientationLandscapeRight) {
    [self correspondToDeviceRotation:270];
    [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeRight animated:YES];

  // 画面が上向き
  } else if (o == UIDeviceOrientationFaceUp) {
    NSLog(@"device orientation is Face Up.");
    // no need actions.

  // 画面が下向き		
  } else if (o == UIDeviceOrientationFaceDown) {
    NSLog(@"device orientation is Face Down.");
    // no need actions.

  // 向きが不明な場合		
  } else {
    NSLog(@"device orientation is Unkown.");
    // no need actions.

  }
}

// 画面上の各種アイテムを回転させるメソッド
- (void) correspondToDeviceRotation : (int)angle {

  // 回転させるためのアフィン変形を作成する
  CGAffineTransform t = CGAffineTransformMakeRotation(angle * M_PI / 180);
	
  // 回転させるのにアニメーションをかけてみた
  [UIView beginAnimations:@"device rotation" context:nil];
  [UIView setAnimationDuration:0.3];
	
  trustButton.transform	= t;  // ゴミ箱ボタン
  undoButton.transform	= t;  // Redoボタン
  redoButton.transform	= t;  // Undoボタン

  // アニメーション開始	
  [UIView commitAnimations];
}

ここでは、デバイスの向きに合わせて、アフィン変換を利用して、ボタンの回転を行っています。アフィン変換の回転については、"ローテーションジェスチャーを簡単に実装する"を参考にしてみて下さい。



独自にデバイスの回転に対応する上で大切なこと

それは、ステータスバーの位置を、デバイスの向きによってちゃんと変える事です。
これを行う事で、新しく開くView(例:UIImagePickerView)などの向きを変えることが出来ます。
動作させたところ、ステータスバーが上になるようにUIViewの向きが決定されるようです。
という事で、ステータスバーの位置変更も忘れず行うと、デバイスの回転に自分で対応することは、出来るようです。



最後に

バイス回転を、「shouldAutorotateToInterfaceOrientation:」メソッドを使わずに行う方法には、かなり悩まされました。
でも、いったんの上記のような解決策を作れて良かったヨカッタ♪(´ε` )
iPhoneアプリ作成では、学ぶ事がホントに多いですね。もっと実力をつけねば。


以下は関連サイトです。参考になれば幸いです。