UIApplicationWillChangeStatusBarOrientationNotification
トリックを行うように見えるKoboで使用しました。必ずしもデバイスがたまたまどこにあるかではなく、UI の選択された向きに一致させたいため、はるかに信頼性が高くなります。つまり、ウィンドウの向きを変更するタイミングを Apple に決定させることができます。
iPad での Kobo アプリのポップアップ ダイアログ コードの一部を次に示します (iPad では UIAlertView が見栄えが悪いので、Richard Pennerがより良いコードを作成しました)。最新の iOS バージョンでいくつかの不具合が発生し、これらのダイアログをさまざまな状況 (方向 IIRC のすべて) で表示する必要があったため、UIWindow 内に直接配置するように微調整する必要がありました。これは、すべての方向変換ロジックを複製することを意味しました。
このコードは、ビューが現在のウィンドウに直接ドロップされる UIViewController からのものです。
- (void) presentDialogWindow
{
// register for orientation change notification
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(orientationWillChange:)
name: UIApplicationWillChangeStatusBarOrientationNotification
object: nil];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(orientationDidChange:)
name: UIApplicationDidChangeStatusBarOrientationNotification
object: nil];
}
- (void) orientationWillChange: (NSNotification *) note
{
UIInterfaceOrientation current = [[UIApplication sharedApplication] statusBarOrientation];
UIInterfaceOrientation orientation = [[[note userInfo] objectForKey: UIApplicationStatusBarOrientationUserInfoKey] integerValue];
if ( [self shouldAutorotateToInterfaceOrientation: orientation] == NO )
return;
if ( current == orientation )
return;
// direction and angle
CGFloat angle = 0.0;
switch ( current )
{
case UIInterfaceOrientationPortrait:
{
switch ( orientation )
{
case UIInterfaceOrientationPortraitUpsideDown:
angle = (CGFloat)M_PI; // 180.0*M_PI/180.0 == M_PI
break;
case UIInterfaceOrientationLandscapeLeft:
angle = (CGFloat)(M_PI*-90.0)/180.0;
break;
case UIInterfaceOrientationLandscapeRight:
angle = (CGFloat)(M_PI*90.0)/180.0;
break;
default:
return;
}
break;
}
case UIInterfaceOrientationPortraitUpsideDown:
{
switch ( orientation )
{
case UIInterfaceOrientationPortrait:
angle = (CGFloat)M_PI; // 180.0*M_PI/180.0 == M_PI
break;
case UIInterfaceOrientationLandscapeLeft:
angle = (CGFloat)(M_PI*90.0)/180.0;
break;
case UIInterfaceOrientationLandscapeRight:
angle = (CGFloat)(M_PI*-90.0)/180.0;
break;
default:
return;
}
break;
}
case UIInterfaceOrientationLandscapeLeft:
{
switch ( orientation )
{
case UIInterfaceOrientationLandscapeRight:
angle = (CGFloat)M_PI; // 180.0*M_PI/180.0 == M_PI
break;
case UIInterfaceOrientationPortraitUpsideDown:
angle = (CGFloat)(M_PI*-90.0)/180.0;
break;
case UIInterfaceOrientationPortrait:
angle = (CGFloat)(M_PI*90.0)/180.0;
break;
default:
return;
}
break;
}
case UIInterfaceOrientationLandscapeRight:
{
switch ( orientation )
{
case UIInterfaceOrientationLandscapeLeft:
angle = (CGFloat)M_PI; // 180.0*M_PI/180.0 == M_PI
break;
case UIInterfaceOrientationPortrait:
angle = (CGFloat)(M_PI*-90.0)/180.0;
break;
case UIInterfaceOrientationPortraitUpsideDown:
angle = (CGFloat)(M_PI*90.0)/180.0;
break;
default:
return;
}
break;
}
}
CGAffineTransform rotation = CGAffineTransformMakeRotation( angle );
[UIView beginAnimations: @"" context: NULL];
[UIView setAnimationDuration: 0.4];
self.view.transform = CGAffineTransformConcat(self.view.transform, rotation);
[UIView commitAnimations];
}
- (void) orientationDidChange: (NSNotification *) note
{
UIInterfaceOrientation orientation = [[[note userInfo] objectForKey: UIApplicationStatusBarOrientationUserInfoKey] integerValue];
if ( [self shouldAutorotateToInterfaceOrientation: [[UIApplication sharedApplication] statusBarOrientation]] == NO )
return;
self.view.frame = [[UIScreen mainScreen] applicationFrame];
[self didRotateFromInterfaceOrientation: orientation];
}
このビュー コントローラをロードし、そのビューをウィンドウに追加してから、次のように -presentModalDialog を呼び出して使用します。
UIView *window = [[UIApplication sharedApplication] keyWindow];
[window addSubview: theController.view];
[theController presentDialogWindow];
簡単な UIViewController サブクラスを作成して、面倒な部分をすぐに実装し、github アカウントに投稿する予定です。その際、これを編集してリンクします。