2015-09-18 29 views
14

In iOS 8 e in basso viene mostrato un UIActionSheet quando viene presentata la tastiera presenterà il foglio azioni sulla tastiera. Con iOS 9 questo non è più il caso.Mostra UIAlertController sulla tastiera

Nella mia app disponiamo di una funzionalità di chat e vogliamo che lo show sia un'azione sulla tastiera. Usavamo UIActionSheet che funzionava bene fino a iOS 8. In iOS 9 il foglio d'azione è presente dietro la tastiera. Ho provato sia UIActionSheet e UIAlertController.

Quello che vogliamo è un foglio di azione come in messages.app Action sheet in messages app.

Ho provato mettendo il foglio di azione in essa una finestra e prioritario canBecomeFirstResponder che ha appena fatto sparire la tastiera.

+0

Sei sicuro di 'UIAlertController'? Ho avuto lo stesso problema nella mia app con 'UIActionSheet' in iOS9 ma quando sono passato al problema' UIAlertController' andato. –

+0

Sì, sono sicuro. Ma sembra accadere solo quando lo si utilizza quando le tastiere sono presenti come parte di una vista 'inputAccessoryView'. – rckoenes

+0

Possibile duplicato di [KEEP tastiera ON quando UIAlertcontroller è presentato in Swift?] (Http://stackoverflow.com/questions/28564710/keep-keyboard-on-when-uialertcontroller-is-presented-in-swift) – galambalazs

risposta

27

Ho implementato esattamente questo nella nostra app. Il trucco è di avere il controller degli avvisi in una finestra diversa. Ecco come funziona l'implementazione UIActionSheet e funziona perfettamente su iOS 8, ma su 9, Apple ha spostato l'implementazione della tastiera in una finestra con un livello di finestra molto alto (10000000). La correzione è di dare alla finestra di avviso un livello di finestra ancora più alto (come doppio valore personalizzato, non usando le costanti fornite).

Quando si utilizza una finestra personalizzata con trasparenza, assicurarsi di leggere my answer here, relativa al colore di sfondo, per evitare che la finestra diventi nera durante le transizioni di rotazione.

_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

Ho avuto provato tutto, ma questo livello di finestra alto. – rckoenes

+0

@rckoenes È davvero fastidioso. Se si esegue un'app SDK8, ha un livello di finestra basso, quindi 'UIActionSheet' funziona correttamente. Ma se l'app utilizza SDK9, va in cielo. È una cospirazione per farti usare 'UIAlertController'.';-)' –

+0

Sto anche usando 'UIAlertController' ma anche quello non ha funzionato e si stava mostrando bene dietro la tastiera: S – rckoenes

-2

uso UIAlertController invece di UIActionSheet

+1

Che non funziona in iOS9, sarà ancora dietro la tastiera. – rckoenes

+0

Anche se questo potrebbe essere un suggerimento prezioso per risolvere il problema, una risposta deve davvero dimostrare la soluzione. Si prega di [modificare] per fornire un codice di esempio per mostrare cosa intendi. In alternativa, considera di scrivere questo come un commento. –

3

in base alla risposta di Leo Natan, ho creato un estensione Swift per presentare un foglio di avviso sulla tastiera.

Nel mio breve test, la finestra di avviso è deallocata dopo che l'avviso è stato chiuso, credo perché non vi è alcun riferimento forte al di fuori dell'allerta. Ciò significa che non è necessario nasconderlo o deallocarlo nelle tue 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

Questo è un modo per fare. Sto usando un sacco di UIAlertController in tutta l'app. Quindi, non voglio deallocare in ogni gestore. Grazie. –

4

La risposta fornita da Leo è rotto come di iOS 11, perché Apple ora si impedisce di impostare un windowLevel sopra 10000000. Una correzione è di attuare un UIWindow personalizzato e ignorare il windowLevel ricevitore:

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

Questo approccio dovrebbe essere compatibile, ma non hanno testato tutte le versioni conosciute. Happy hacking!

Problemi correlati