2015-09-30 20 views
21

La domanda è simile a iOS 8 UIActivityViewController and UIAlertController button text color uses window's tintColor ma in iOS 9.Come cambiare il colore del testo del pulsante UIAlertController in iOS9?

Ho un UIAlertController e il pulsante di respingere mantiene il colore bianco anche io ho cercato di impostare

[[UIView appearanceWhenContainedIn:[UIAlertController class], nil] setTintColor:[UIColor blackColor]]; 

UIAlertController *strongController = [UIAlertController alertControllerWithTitle:title 
                  message:message 
                 preferredStyle:preferredStyle]; 
strongController.view.tintColor = [UIColor black]; 

risposta

50

ho incontrato qualcosa di simile nel passato e il problema sembra derivare dal fatto che la vista del controller di avviso non è pronta ad accettare le modifiche tintColor prima di essere presentata. In alternativa, provare a impostare il colore della tinta DOPO si presenti il ​​controller avviso:

[self presentViewController:strongController animated:YES completion:nil]; 
strongController.view.tintColor = [UIColor black]; 
+2

Ho provato ma non lavoro per me. – RayChen

+0

Assicurati di non avere altre parti del tuo codice che possono sovrascrivere il 'tintColor' (ad es. Impostazioni globali tramite proxy di aspetto, ecc.). – dbart

+0

grazie, funziona dopo la rimozione della finestra chiave tintColor – RayChen

2

ho trovato una soluzione a questo. Non una soluzione elegante, ma una soluzione.

Ho visualizzato una vista a rafficaWillAppear: su UIAlertController, quindi ho eseguito il ciclo delle viste e modificato il colore della tinta. Nel mio caso ho avuto un tintColor impostato sull'intera finestra e nonostante l'impostazione del tintColor tramite l'aspetto il controller UIAlert ha mantenuto il colore sulla finestra. Controllo se il colore è uguale a quello della finestra e in tal caso ne applico uno nuovo. Applicando il TintColor in modo invisibile a tutte le viste, la tinta rossa sulle azioni distruttive deve essere ripristinata.

+ (void)load 
{ 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     Method swizzleMethod = class_getInstanceMethod(self, @selector(viewWillAppear:)); 
     Method method = class_getInstanceMethod(self, @selector(alertSwizzle_viewWillAppear:)); 
     method_exchangeImplementations(method, swizzleMethod); 
    }); 
} 

- (void)alertSwizzle_viewWillAppear:(BOOL)animated 
{ 
    [self alertSwizzle_viewWillAppear:animated]; 
    [self applyTintToView:self.view]; 
} 

- (void)applyTintToView:(UIView *)view 
{ 
    UIWindow *mainWindow = [UIApplication sharedApplication].keyWindow; 

    for (UIView *v in view.subviews) { 
     if ([v.tintColor isEqual:mainWindow.tintColor]) { 
      v.tintColor = [UIColor greenColor]; 
     } 
     [self applyTintToView:v]; 
    } 
} 

Tuttavia questo non funziona su iOS 8, così avrai ancora bisogno per impostare il colore apperance tinta.

[[UIView appearanceWhenContainedIn:[UIAlertController class], nil] setTintColor:[UIColor greenColor]]; 
12

ho potuto risolvere questa sottoclasse UIAlertController:

class MyUIAlertController: UIAlertController { 

    override func viewWillLayoutSubviews() { 
     super.viewWillLayoutSubviews() 

     //set this to whatever color you like... 
     self.view.tintColor = UIColor.blackColor() 
    } 
} 

Questo sopravvive una rotazione periferica mentre l'avviso viene visualizzato.

Inoltre, non è necessario impostare tintColor dopo aver presentato l'avviso quando si utilizza questa sottoclasse.

Sebbene non sia necessario su iOS 8.4, questo codice funziona anche su iOS 8.4.

implementazione Objective-C dovrebbe essere qualcosa di simile:

@interface MyUIAlertController : UIAlertController 
@end 

@implementation MyUIAlertController 
-(void)viewWillLayoutSubviews { 
    [super viewWillLayoutSubviews]; 

    //set this to whatever color you like... 
    self.view.tintColor = [UIColor blackColor]; 
} 
@end 
+0

Non sono documenti iOS su https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIAlertController_class/ in particolare dice "Sottoclasse Note The UIAlertController la classe è concepita per essere utilizzata così com'è e non supporta la sottoclassi La gerarchia della vista per questa classe è privata e non deve essere modificata. " – dkzm

+0

Interessante. Sto sottoclasse ma non modifica la gerarchia della vista. Puoi vedere che la sottoclasse non fa altro che impostare il colore della tinta. Speriamo che Apple aggiusterà la loro classe, quindi non è necessario. –

4

C'è un problema con l'impostazione del colore di tinta sulla vista dopo aver presentato; anche se lo si fa nel blocco di completamento di presentViewController: animato: completamento:, provoca un effetto sfarfallio sul colore dei titoli dei pulsanti. Questo è sciatto, poco professionale e completamente inaccettabile.

L'unico modo sicuro per risolvere questo problema e farlo ovunque, è aggiungendo una categoria a UIAlertController e facendo girare la vistaWillAppear.

L'intestazione:

// 
// UIAlertController+iOS9TintFix.h 
// 
// Created by Flor, Daniel J on 11/2/15. 
// 

#import <UIKit/UIKit.h> 

@interface UIAlertController (iOS9TintFix) 

+ (void)tintFix; 

- (void)swizzledViewWillAppear:(BOOL)animated; 

@end 

L'implementazione:

// 
// UIAlertController+iOS9TintFix.m 
// 
// Created by Flor, Daniel J on 11/2/15. 
// 

#import "UIAlertController+iOS9TintFix.h" 
#import <objc/runtime.h> 

@implementation UIAlertController (iOS9TintFix) 

+ (void)tintFix { 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     Method method = class_getInstanceMethod(self, @selector(viewWillAppear:)); 
     Method swizzle = class_getInstanceMethod(self, @selector(swizzledViewWillAppear:)); 
     method_exchangeImplementations(method, swizzle);}); 
} 

- (void)swizzledViewWillAppear:(BOOL)animated { 
    [self swizzledViewWillAppear:animated]; 
    for (UIView *view in self.view.subviews) { 
     if (view.tintColor == self.view.tintColor) { 
      //only do those that match the main view, so we don't strip the red-tint from destructive buttons. 
      self.view.tintColor = [UIColor colorWithRed:0.0 green:122.0/255.0 blue:1.0 alpha:1.0]; 
      [view setNeedsDisplay]; 
     } 
    } 
} 

@end 

Aggiungere a.PCH (intestazione precompilata) al progetto e comprendono la categoria:

#import "UIAlertController+iOS9TintFix.h" 

Assicurarsi si registra il PCH nel progetto correttamente, e comprenderà i metodi di categoria in ogni classe che utilizza l'UIAlertController.

Poi, nel metodo di vostra applicazione delegati didFinishLaunchingWithOptions, importare la categoria e chiamare

[UIAlertController tintFix]; 

e sarà automaticamente propagarsi ad ogni singola istanza di UIAlertController all'interno della vostra app, se lanciato dal codice o di chiunque altro.

Questa soluzione funziona sia per iOS 8.X che per iOS 9.X e manca lo sfarfallio del cambio di tonalità dopo la presentazione.

Oggetti di scena pazzi a Brandon sopra per iniziare questo viaggio, purtroppo la mia reputazione non è stata sufficiente per commentare il suo post, altrimenti l'avrei lasciato lì!

+3

Non direi che i metodi di swizzling per questo scopo sono molto più professionali ... – MrTJ

3
[[UIView appearance] setTintColor:[UIColor black]]; 

questo cambierà tutto il UIView tintColor così come vista UIAlertController s'

+0

Ancora funziona in IOS 11.2.1 - L'ho usato per cambiare i colori della tinta del pulsante di dialogo predefinito Apple. – Wayne

8

Objective-C

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Title text" message:@"Message text" preferredStyle:UIAlertControllerStyleAlert]; 
UIAlertAction* ok = [UIAlertAction actionWithTitle:@"Yes" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { 
//code here… 
}]; 
UIAlertAction* cancel = [UIAlertAction actionWithTitle:@"Later" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { 
//code here…. 
}]; 
[ok setValue:[UIColor greenColor] forKey:@"titleTextColor"]; 
[cancel setValue:[UIColor redColor] forKey:@"titleTextColor"]; 
[alertController addAction:ok]; 
[alertController addAction:cancel]; 
[alertController.view setTintColor:[UIColor yellowColor]]; 
[self presentViewController:alertController animated:YES completion:nil]; 

Swift 3

let alertController = UIAlertController(title: "Title text", message: "Message text", preferredStyle: .alert) 
let ok = UIAlertAction(title: "Yes" , style: .default) { (_ action) in 
      //code here… 
     } 
let cancel = UIAlertAction(title: "Later" , style: .default) { (_ action) in 
      //code here… 
     } 
ok.setValue(UIColor.green, forKey: "titleTextColor") 
cancel.setValue(UIColor.red, forKey: "titleTextColor") 
alertController.addAction(ok) 
alertController.addAction(cancel) 
alertController.view.tintColor = .yellow 
self.present(alertController, animated: true, completion: nil) 
1

In Swift 2.2 è possibile utilizzare seguente codice

// LogOut or Cancel 
    let logOutActionSheet: UIAlertController = UIAlertController(title: "Hello Mohsin!", message: "Are you sure you want to logout?", preferredStyle: .Alert) 

    self.presentViewController(logOutActionSheet, animated: true, completion: nil) 

    let cancelActionButton: UIAlertAction = UIAlertAction(title: "Cancel", style: .Cancel) { action -> Void in 
     print("Cancel Tapped") 
    } 

    logOutActionSheet.addAction(cancelActionButton) 

    let logOutActionButton: UIAlertAction = UIAlertAction(title: "Clear All", style: .Default) 
    { action -> Void in 
     //Clear All Method 
     print("Logout Tapped") 

    } 

    logOutActionButton.setValue(UIColor.redColor(), forKey: "titleTextColor") 

    logOutActionSheet.addAction(logOutActionButton) 
1

che è possibile sostituire con: Swift 3.x

strongController.view.tintColor = UIColor.green 
5

In 3.x Swift:

Ho trovato quanto segue per funzionare efficacemente. Lo chiamo al lancio di app.

UIView.appearance(whenContainedInInstancesOf: [UIAlertController.self]).tintColor = UIColor.black 

Così questo cambierebbe il colore della tinta di tutte le etichette del pulsante UIAlertViewController nell'app a livello globale. L'unico colore dell'etichetta del pulsante che non cambia sono quelli che hanno un UIAlertActionStyle di tipo distruttivo.

0

Hai 3 stili per i pulsanti di azione:

let style : UIAlertActionStyle = .default 
// default, cancel (bold) or destructive (red) 

let alertCtrl = UIAlertController(....) 
alertCtrl.addAction(UIAlertAction(title: "click me", style: style, handler: { 
    _ in doWhatever() 
})) 
0

ho voluto fare il tasto di cancellazione per apparire rossa, quindi ho usato stile .destructive:

alert.addAction(UIAlertAction(title: "Delete", style: .destructive, handler:{(UIAlertAction) in 
3

swift3

Provato per utilizzare UIView.appearance(whenContainedInInstancesOf: [UIAlertController.self]).tintColor = MyColor ma questo impedisce altri elementi non correlati a UIAlertController dalla configurazione tintColor. L'ho visto mentre cercavo di cambiare il colore delle voci dei pulsanti della barra di navigazione.

Sono passato a un'estensione (basata sulla risposta di Mike Taverne sopra) e funziona benissimo.

extension UIAlertController { 

override open func viewWillLayoutSubviews() { 
    super.viewWillLayoutSubviews() 

    //set this to whatever color you like... 
    self.view.tintColor = MyColor 
} 
} 
+0

Ben fatto! Funziona su iOS 9.3, Xcode 9 Beta 5 – Womble

Problemi correlati