【UIVIewController】iPhoneを横向きにした時に別画面を表示する方法

Posted by: daichi  /  Category: iphone開発

これだいぶやられました。
こんな風にただ横向きに画面を表示したいだけなのですが、ハマり倒しました。

横向き画面

二度とやられないためにもここに残します。


本体回転の検知

横向きにした時に別画面を表示するには、まず横向きを検知する必要があります。
UIViewControllerの以下のメソッドで本体の回転状態を検知できます。

?View Code OBJECTIVE-C
 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {


このメソッドでNOを返せばViewの自動回転をしない、YESを返せば自動回転をする、という設定になります。
が、加えて引数のinterfaceOrientationの状態を見れば本体がどの向きになっているのかを検知できます。

UIInterfaceOrientationはenumで値はそれぞれ以下の状態を表します。
  • UIInterfaceOrientationPortrait
  • これはホームボタンが画面の下側にある状態。通常の状態。
  • UIInterfaceOrientationPortraitUpsideDown
  • これはホームボタンが画面の上側にある状態。通常と逆さまの状態。
  • UIInterfaceOrientationLandscapeLeft
  • これはホームボタンが画面の左側にある状態。右に傾けた状態。
  • UIInterfaceOrientationLandscapeRight
  • これはホームボタンが画面の右側にある状態。左に傾けた状態。
本体を横向きにした場合に、別画面を表示するコードはこんな感じ。

?View Code OBJECTIVE-C
 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
       //ホームボタンが下以外にある状態なら
 	if (UIInterfaceOrientationPortrait != interfaceOrientation){
 
		iPachiAppDelegate *delegate = (iPachiAppDelegate *)[[UIApplication sharedApplication] delegate];
 
               // Fade In Out のアニメーションで表示
		CATransition* animation;
		animation = [CATransition animation];
		animation.type = kCATransitionFade;
 
		[[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES];
 
		GraffController *graff = [ControllerManager graffController];
		UITabBarController *tab = delegate.tabBarController;
 
		[tab.view removeFromSuperview];
		UIView *win = delegate.window;
		[win addSubview:graff.view];
 
		[win.layer addAnimation:animation forKey:nil];
 
	}
    return NO;
}


アニメーションでFade in out させて別画面を起動させています。
最後にNOをreturnしているのは、呼び出し元画面を自動回転させないため。
あくまで横向き時に別画面を呼び出すことにとどめています。

横向き画面用に座標を変換

上の状態では画面を起動することはできますが、座標がホームボタンの左上になっているため、こんな画面になってしまいます。

横向きになりきれていない

背景画像も横向きサイズで用意したため、見事に縦に足りず、横にはみ出ています。

まずはViewのframeを横向きサイズに変更します。
ここでは呼び出し先のloadViewメソッドでframeを指定します。

?View Code OBJECTIVE-C
- (void)loadView {
	CGRect frame = [[UIScreen mainScreen] applicationFrame];
	UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, frame.size.height, frame.size.width)];
	view.autoresizesSubviews = YES;
	self.view = view;
	[view release];
}


Interface Builderを使用している場合は、IB上でframeを横向きサイズに指定しておきます。

これで呼び出し先のビューでdrawRectしている内容も横向きサイズ内で描画されるようになります。こんな感じ。

横向きフレーム補正

次に、左下になっているUIViewの原点を横向きにした時に左上にくるように座標を変換します。
座標の変換にはCGAffineTransformを使います。

コードからみてしまうとこんな感じ

?View Code OBJECTIVE-C
- (void)viewWillAppear:(BOOL)animated {
	CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI * 90 / 180.0f);
	transform = CGAffineTransformTranslate(transform, 80, 80);
	self.view.transform = transform;
}


CGAffineTransformMakeRotationで引数にM_PI * 90 / 180.0fを与えていますが、こいつで座標を時計回りに90°回転させています。
ちなみに90°回転させた状態はこんな感じになります。

90°回転

どうも回転は描画前のcenterを中心に行われるようです。たぶん。

次のCGAffineTransformTranslateで描画位置を移動させます。
ここではx軸に80px,y軸に80px移動させます。
x軸は右が、y軸は下が正の値です。

これをすると左上にずれてしまっているviewが右下に移動してこの形になります。

横向き正常

ですが、このままでは反対の横に回転させるとこんな画面になってしまいます。

横向き反対

今は、呼び出し元画面時に左右どちらに傾けようが、常に時計周りに座標を変換してしまっているためです。

なので呼び出し元での傾ける方向を呼び出し先画面に渡して、その値によって傾ける方向を変えてやります。

呼び出し元のコードは以下。

?View Code OBJECTIVE-C
 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
       //ホームボタンが下以外にある状態なら
 	if (UIInterfaceOrientationPortrait != interfaceOrientation){
 
		iPachiAppDelegate *delegate = (iPachiAppDelegate *)[[UIApplication sharedApplication] delegate];
 
               // Fade In Out のアニメーションで表示
		CATransition* animation;
		animation = [CATransition animation];
		animation.type = kCATransitionFade;
 
		[[UIApplication sharedApplication] setStatusBarHidden:YES animated:YES];
 
		GraffController *graff = [ControllerManager graffController];
 
     // 画面の向きを渡す
     graff.parentUIInterfaceOrientation = interfaceOrientation;
 
		UITabBarController *tab = delegate.tabBarController;
 
		[tab.view removeFromSuperview];
		UIView *win = delegate.window;
		[win addSubview:graff.view];
 
		[win.layer addAnimation:animation forKey:nil];
 
	}
    return NO;
}


呼び出し先のコードは以下。

?View Code OBJECTIVE-C
- (void)viewWillAppear:(BOOL)animated {
       // 右にホームボタンがある場合
	if (self.parentUIInterfaceOrientation == UIInterfaceOrientationLandscapeRight ){
    // 90°時計回りに回転
		CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI * 90 / 180.0f);
		transform = CGAffineTransformTranslate(transform, 80, 80);
		self.view.transform = transform;	
 
       // 左にホームボタンがある場合
	} else if (self.parentUIInterfaceOrientation == UIInterfaceOrientationLandscapeLeft ){
    // 90°半時計回りに回転
		CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI * 270 / 180.0f);
		transform = CGAffineTransformTranslate(transform, -80, -80);
		self.view.transform = transform;
	}
}


呼び出し先にはこんな変数を定義しています。
UIInterfaceOrientation parentUIInterfaceOrientation;

ここまでで、横向き起動完了です。

おつかれさまです。

関連のあるアプリ

islot_icon
iSlot Pro 2009/03/13 リリース
ファイナンス 350円
パチスロ収支管理アプリ
app_store_badge

タグ: Interface Builder, iPachi, iphone, iSlot, iSlot Pro, objecti, objective-c, UIViewController, アプリ, パチスロ, リリース, 収支, 回転, 変換, 検知, 横向き

関連する投稿

One Response to “【UIVIewController】iPhoneを横向きにした時に別画面を表示する方法”

  1. アプリをiPhone OS 3.0へ対応させる時がきました | iphoneアプリで稼げるのか Says:

    [...] 【UIVIewController】iPhoneを横向きにした時に別画面を表示する方法 | iphoneアプリで稼げるのか [...]

コメント

Get Adobe Flash playerPlugin by wpburn.com wordpress themes