2010年3月25日木曜日

iPhoneアプリで縦画面を横にした時に左上を基準に縦画面をフィットさせて表示するには?

iPhoneアプリで縦画面を横モードにした時、多くの場合は自動リサイズが発生するのでそれにあわせて再レイアウトする処理をするだろう。ただ、再レイアウトは結構面倒だ。

単に縦画面を横モード時にフィットさせて表示させたいだけなら、再レイアウトを使わずにCGAffineTransformを使ってスケーリングするといい。

下記のようなコードを自分のViewControllerに追加する。

/**
 *
 * これから変更しようとするデバイスの向きを許可する
 *(これがないとiPhoneを回転させても画面の向きが変わらない)
 *
 */
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
 NSLog(@"デバイスの向きはどの方向でも変更してよし!");
 return YES;
}


/**
 *
 * デバイスの向き変更(回転)開始
 *
 */
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)_toInterfaceOrientation duration:(NSTimeInterval)duration {
 
 //toInterfaceOrientationを保存
 toInterfaceOrientation = _toInterfaceOrientation;
 
 if (toInterfaceOrientation == UIInterfaceOrientationPortrait || 
  toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
  NSLog(@"デバイスの向き変更開始:縦へ");
  targetView.transform = CGAffineTransformMakeScale(1.0, 1.0);
 } else {
  NSLog(@"デバイスの向き変更開始:横へ");
  // 300(横モード時の高さ) / 460(縦モード時の高さ) = 0.652
  targetView..transform = CGAffineTransformMakeScale(0.652, 0.652);
 }

 //スケーリングで左上の位置がずれるので、いずれにしても(0, 0)座標に移動させる
 CGRect frame = targetView.frame;
 frame.origin.x = 0;
 frame.origin.y = 0;
 targetView.frame = frame;
 
}


/**
 *
 * デバイスの向き変更(回転)完了
 *
 */
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
 //fromInterfaceOrientationだけでは縦になったのか横になったのか判断出来ないので
 //保存しておいたtoInterfaceOrientationを使って判断する
 if (toInterfaceOrientation == UIInterfaceOrientationPortrait || 
  toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
  NSLog(@"デバイスの向き変更完了:縦");
 } else {
  NSLog(@"デバイスの向き変更完了:横");
 }
}


ただし、CGAffineTransformMakeScaleを使うにはCoreGraphics.frameworkを追加しておく必要がある。

「追加」>「既存のフレームワーク」でCoreGraphics.frameworkの候補が出てこなかったので、左下の「その他を追加」ボタンから下記のフォルダを直接指定して追加した。

/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.1.3.sdk/System/Library/Frameworks/CoreGraphics.framework

ヘッダーファイルをインクルードしなくてもコンパイルできたので、特にヘッダーのインクルードは必要はないようだ。