UIView
の動作のように、すべてのビューの上にUIAlertView
を作成するための最良の方法は、ビューをアプリウィンドウに追加することです。
[[[UIApplication sharedApplication] delegate] window]
しかし、私が見つけた欠点は、ローテーションが自動的に行われないことです。ローテーションを取得するための最善の方法は、現在のAppDelegate window.navigationController
/rootViewController
にビューを追加することです。ただし、これを行うと、すべての上に表示されなくなります。ビューが表示されているときにmodalViewControllerポップアップが表示された場合、モーダルビューがビューを確実に覆います。
私の質問は、最上位のウィンドウにサブビューを追加することは可能ですか?and support orientation?この場合、2セットのNibファイルが必要ですか? UIAlertView
は、最上部と方向のサポートを組み合わせるマジックをどのようにしていますか? UIAlertView.h
を調べると、実際には2つのUIWindows
があり、1つはoriginalWindow
と呼ばれ、もう1つはdimWindow
と呼ばれます。 UIAlertView.m
のソースコードを見つけることができる場所はありますか?
私が見つけた最良の解決策は、透明なコンテナビューを作成し、そのコンテナをウィンドウに追加し、アラートをコンテナ内に配置することです。その後、UIApplicationWillChangeStatusBarOrientationNotification
に登録して、回転イベントを受信し、コンテナーを変換できます。これにより、アラートのフレームを個別に操作できます。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
self.container = [[UIView alloc] initWithFrame:self.window.bounds];
[self.container addSubview:self.alertView];
[self.window addSubview:self.container];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(statusBarWillRotate:)
name:UIApplicationWillChangeStatusBarOrientationNotification
object:nil];
...
}
...
- (void)statusBarWillRotate:(NSNotification *)theNotification
{
CGFloat rotation = 0;
switch ([notification[UIApplicationStatusBarOrientationUserInfoKey] intValue])
{
case UIInterfaceOrientationLandscapeLeft:
rotation = -M_PI_2;
break;
case UIInterfaceOrientationLandscapeRight:
rotation = M_PI_2;
break;
case UIInterfaceOrientationPortraitUpsideDown:
rotation = M_PI;
break;
case UIInterfaceOrientationPortrait:
default:
rotation = 0;
break;
}
CGAffineTransform rotationTransform = CGAffineTransformMakeRotation(rotation);
CGSize rotatedSize = CGRectApplyAffineTransform(self.window.bounds, rotationTransform).size;
[UIView animationWithDuration:[UIApplication sharedApplication].statusBarOrientationAnimationDuration
animations:^{
self.container.transform = rotationTransform;
// Transform invalidates the frame, so use bounds/center
self.container.bounds = CGRectMake(0, 0, rotatedSize.width, rotatedSize.height);
self.container.center = CGPointMake(self.window.bounds.size.width / 2, self.window.bounds.size.height / 2);
}];
}
本当に必要な場合は、windowLevel
プロパティをUIWindowLevelAlert
に設定してまったく新しいウィンドウを作成できます。これにより、ウィンドウはキーボードを含む他のすべてのビューの上に残りますが、ウィンドウ管理かなりトリッキーになります。上記のソリューションは、ほとんどのニーズに十分なはずです。
View Controllerのビューをウィンドウに単純に追加する場合の問題は、すべての回転とview[Will|Did][Disa|A]ppear:
メッセージ(View Controllerに追加されない場合)階層 via addChildViewController:
ルートビューコントローラ。
UIWindow
の最初のサブビューのみが方向の変更について通知されます。 (<iOS8)
あなたの質問はこれに非常に似ています:
そこの答えが示すように、方向の変更の通知に登録し、「トップ」サブビューの再レイアウトをそのように処理できます。
これが可能な解決策です。いくつかのステップで説明しています。
UIViewController
の代わりにUIView
継承クラスで開始、TopViewController
によって継承されたUIViewController
という名前のクラスとしましょうTopViewController
から継承されたUIViewController
クラスには、View Rotation Eventsに応答するメソッドがあります。ローテーションイベントをキャプチャできるようになりました。最後に、質問で説明したのと同じ方法を使用して、TopViewController
ビューをUIWindow
の上部に配置できます。
[[[[UIApplication sharedApplication] delegate] window] addSubview:(TopViewController object).view];
お役に立てれば。