IOS 8以下では、キーボードが表示されたときにUIActionSheet
を表示すると、キーボードの上にアクションシートが表示されます。 iOS 9では、これはもはや当てはまりません。
私のアプリにはチャット機能があり、キーボードを介してアクションを表示する必要があります。以前はUIActionSheet
を使用していましたが、iOS 8までは正常に機能していました。iOS9では、アクションシートはキーボードの後ろにあります。 UIActionSheet
とUIAlertController
の両方を試しました。
私たちが欲しいのはmessages.appのようなアクションシートです
アクションシートを独自のウィンドウに配置し、キーボードが消えたcanBecomeFirstResponder
をオーバーライドしてみました。
私はこれをアプリに正確に実装しました。秘訣は、アラートコントローラーを別のウィンドウに表示することです。これはUIActionSheet
実装がそれを行う方法であり、iOS 8でうまく機能しますが、9では、Appleは、キーボード実装を非常に高いウィンドウレベルのウィンドウに移動しました(10000000)。修正は、アラートウィンドウにさらに高いウィンドウレベルを与えることです(提供された定数を使用せずに、カスタムのdouble値として)。
透明度のあるカスタムウィンドウを使用する場合は、回転遷移中にウィンドウが黒くなるのを防ぐために、背景色について ここでの私の答え を必ず読んでください。
_alertWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
_alertWindow.rootViewController = [UIViewController new];
_alertWindow.windowLevel = 10000001;
_alertWindow.hidden = NO;
_alertWindow.tintColor = [[UIWindow valueForKey:@"keyWindow"] tintColor];
__weak __typeof(self) weakSelf = self;
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Test" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
weakSelf.alertWindow.hidden = YES;
weakSelf.alertWindow = nil;
}]];
[alert addAction:[UIAlertAction actionWithTitle:@"Test" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
weakSelf.alertWindow.hidden = YES;
weakSelf.alertWindow = nil;
}]];
[_alertWindow.rootViewController presentViewController:alert animated:YES completion:nil];
Appleは、windowLevelを10000000
より上に設定できないようになったため、Leoによって提供された答えは壊れています。修正は、カスタムUIWindowを実装し、windowLevel
レシーバーをオーバーライドすることです。 :
@interface TopWindow : UIWindow @end
@implementation TopWindow
- (UIWindowLevel) windowLevel {
return 20000000.000;
}
@end
// usage:
UIWindow* w = [[TopWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
w.rootViewController = [UIViewController new];
w.hidden = NO;
[w.rootViewController presentViewController:yourActionSheetController animated:YES completion:nil];
このアプローチには下位互換性があるはずですが、すべての既知のバージョンをテストしているわけではありません。ハッピーハッキング!
Leo Natanの回答に基づいて、キーボード上にアラートシートを表示するためのSwift拡張機能を作成しました。
私の簡単なテストでは、alertWindowはアラートが閉じられた後に割り当てが解除されます。これは、アラートの外部に強い参照がないためだと思います。これは、UIAlertActionsで非表示にしたり割り当てを解除したりする必要がないことを意味します。
extension UIAlertController {
func presentOverKeyboard(animated: Bool, completion: (() -> Void)?) {
let alertWindow = UIWindow(frame: UIScreen.mainScreen().bounds)
// If you need a white/hidden/other status bar, use an appropriate VC.
// You may not need a custom class, and you can just use UIViewController()
alertWindow.rootViewController = whiteStatusBarVC()
alertWindow.windowLevel = 10000001
alertWindow.hidden = false
// Set to a tint if you'd like
alertWindow.tintColor = UIColor.greenColor()
alertWindow.rootViewController?.presentViewController(self, animated: animated, completion: completion)
}
}
private class whiteStatusBarVC: UIViewController {
private override func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
}