2015-09-18 3 views
14

В iOS 8 и ниже показать UIActionSheet, когда клавиатура представлена, будет представлен лист действий над клавиатурой. С iOS 9 это уже не так.Показать UIAlertController over keyboard

В моем приложении у нас есть функция чата и вы хотите показать действие над клавиатурой. Раньше мы использовали UIActionSheet, который работал нормально до iOS 8. В iOS 9 экран действий присутствует за клавиатурой. Я пробовал и UIActionSheet, и UIAlertController.

Что мы хотим, чтобы это действие лист, как в messages.app Action sheet in messages app.

Я попытался поместить лист действий в нем собственном окне и наиважнейшей canBecomeFirstResponder, который только что сделал клавиатура исчезнет.

+0

Вы уверены, что используете 'UIAlertController'? У меня была такая же проблема в моем приложении с «UIActionSheet» в iOS9, но когда я переключился на проблему «UIAlertController», ушел. –

+0

Да, я уверен. Но похоже, что это происходит только тогда, когда вы используете его, когда клавиатура присутствует как часть представления 'inputAccessoryView'. – rckoenes

+0

Возможный дубликат [KEEP-клавиатуры ВКЛ, когда UIAlertcontroller представлен в Swift?] (Http://stackoverflow.com/questions/28564710/keep-keyboard-on-when-uialertcontroller-is-presented-in-swift) – galambalazs

ответ

27

Я реализовал именно это в нашем приложении. Хитрость заключается в том, чтобы контроллер предупреждения отображался в другом окне. Вот как это делает реализация UIActionSheet и отлично работает на iOS 8, но на 9 Apple переместила реализацию клавиатуры в окно с очень высоким уровнем окна (10000000). Исправление состоит в том, чтобы дать вашему окну предупреждения еще более высокий уровень окна (как пользовательское двойное значение, не используя предоставленные константы).

При использовании пользовательского окна, которое будет иметь прозрачность, обязательно прочитайте my answer here относительно цвета фона, чтобы окно не становилось черным во время переходов вращения.

_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]; 

enter image description here

+0

У меня было пробовал все, но этот высокий уровень окна. – rckoenes

+0

@ rckoenes Это действительно раздражает. Если вы запускаете приложение SDK8, у него низкий уровень окна, поэтому 'UIActionSheet' работает хорошо. Но если приложение использует SDK9, оно идет в небо. Это заговор, чтобы заставить вас использовать 'UIAlertController'.';-)' –

+0

Я даже использую 'UIAlertController', но даже это не помогло и отлично показалось за клавиатурой: S – rckoenes

-2

использование UIAlertController вместо UIActionSheet

+1

Это не работает в iOS9, оно по-прежнему будет за клавиатурой. – rckoenes

+0

Хотя это может быть ценным советом для решения проблемы, ответ действительно должен продемонстрировать решение. Пожалуйста, [править], чтобы предоставить пример кода, чтобы показать, что вы имеете в виду. В качестве альтернативы подумайте о том, чтобы вместо этого писать это как комментарий. –

3

На основании ответа Лео Натана, я создал 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 
    } 
} 
+0

Это один из способов сделать. Я использую много UIAlertController во всем приложении. Поэтому я не хочу освобождать каждого обработчика. Благодарю. –

4

Ответ поставляется Лео сломана, как ИО 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]; 

Этот подход должен иметь обратную совместимость, но не протестированы все известные версии. Счастливый взлом!

Смежные вопросы