Показать UIAlertController через клавиатуру
В iOS 8 и ниже покажите a UIActionSheet
, когда представленная клавиатура представит план действий над клавиатурой. С iOS 9 это уже не так.
В моем приложении у нас есть функция чата и вы хотите показать действие над клавиатурой. Раньше мы использовали UIActionSheet
, который отлично работал до iOS 8. В iOS 9 за клавиатурой присутствует лист действий. Я пробовал как UIActionSheet
, так и UIAlertController
.
Что нам нужно - это панель действий, например, в messages.app
![Таблица действий в приложении сообщений.]()
Я попытался помещать лист действий в его собственное окно и переопределять canBecomeFirstResponder
, который просто запустил клавиатуру.
Ответы
Ответ 1
Я реализовал именно это в нашем приложении. Хитрость заключается в том, чтобы контроллер предупреждения отображался в другом окне. Вот как это делает реализация UIActionSheet
и отлично работает на iOS 8, но на 9 Apple переместила реализацию клавиатуры в окно с очень высоким уровнем окна (10000000). Исправление состоит в том, чтобы дать вашему окну предупреждений еще более высокий уровень окна (как пользовательское двойное значение, не используя предоставленные константы).
При использовании пользовательского окна, которое будет иметь прозрачность, обязательно прочитайте мой ответ здесь относительно цвета фона, чтобы окно не становилось черным во время переходов вращения.
_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];
![введите описание изображения здесь]()
Ответ 2
Основываясь на ответе Лео Натана, я создал расширение 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
}
}
Ответ 3
Ответ, поставленный Лео, сломан как iOS 11, потому что Apple теперь не позволяет вам устанавливать windowLevel выше 10000000
. Исправление состоит в том, чтобы реализовать пользовательский интерфейс 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];
Этот подход должен быть обратно совместимым, но не проверял все известные версии. Счастливый взлом!
Ответ 4
используйте UIAlertController вместо UIActionSheet