これだいぶやられました。
こんな風にただ横向きに画面を表示したいだけなのですが、ハマり倒しました。
二度とやられないためにもここに残します。
本体回転の検知
横向きにした時に別画面を表示するには、まず横向きを検知する必要があります。
UIViewControllerの以下のメソッドで本体の回転状態を検知できます。
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { |
このメソッドでNOを返せばViewの自動回転をしない、YESを返せば自動回転をする、という設定になります。
が、加えて引数のinterfaceOrientationの状態を見れば本体がどの向きになっているのかを検知できます。
UIInterfaceOrientationはenumで値はそれぞれ以下の状態を表します。
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
これはホームボタンが画面の下側にある状態。通常の状態。
これはホームボタンが画面の上側にある状態。通常と逆さまの状態。
これはホームボタンが画面の左側にある状態。右に傾けた状態。
これはホームボタンが画面の右側にある状態。左に傾けた状態。
本体を横向きにした場合に、別画面を表示するコードはこんな感じ。
- (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を指定します。
- (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を使います。
コードからみてしまうとこんな感じ
- (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°回転させた状態はこんな感じになります。
どうも回転は描画前のcenterを中心に行われるようです。たぶん。
次のCGAffineTransformTranslateで描画位置を移動させます。
ここではx軸に80px,y軸に80px移動させます。
x軸は右が、y軸は下が正の値です。
これをすると左上にずれてしまっているviewが右下に移動してこの形になります。
ですが、このままでは反対の横に回転させるとこんな画面になってしまいます。
今は、呼び出し元画面時に左右どちらに傾けようが、常に時計周りに座標を変換してしまっているためです。
なので呼び出し元での傾ける方向を呼び出し先画面に渡して、その値によって傾ける方向を変えてやります。
呼び出し元のコードは以下。
- (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;
} |
呼び出し先のコードは以下。
- (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;
ここまでで、横向き起動完了です。
おつかれさまです。








5月 9th, 2009 at 10:26 AM
[...] 【UIVIewController】iPhoneを横向きにした時に別画面を表示する方法 | iphoneアプリで稼げるのか [...]
9月 18th, 2010 at 12:46 AM
As your faith is strengthened you will-power find that there is no longer the emergency to have a intelligibility of control, that things commitment flow as they at one’s desire, and that you will course with them, to your extraordinary gladden and benefit.
[url=http://petitelectromenager.eu]Aspirateurs Electrolux[/url]
Cafetières Senseo
4月 3rd, 2011 at 4:04 AM
ソースの中にあるControllerManagerとはなんですか。教えていただければありがたいです。
4月 27th, 2012 at 6:31 PM
まぁどっちでもいいんですが、
回転前のView中心をUIWindowの中心に合わせて回転させる方がスマートな気がします、場合分けが要らないですし。
でも、逆さまも必要なら参考演算子じゃどうにもならないなぁ。。。
CGAffineTransformRotate(CGAffineTransformMakeTranslation(-80.0f,80.0f),M_PI / 0.5f * (self.parentUIInterfaceOrientation == UIInterfaceOrientationLandscapeRight ? 1.0f : -1.0f));