Carattere, dimensione, colore personalizzati di UIAlertController


118

Sto usando il nuovo UIAlertController per mostrare gli avvisi. Ho questo codice:

// nil titles break alert interface on iOS 8.0, so we'll be using empty strings
UIAlertController *alert = [UIAlertController alertControllerWithTitle: title == nil ? @"": title message: message preferredStyle: UIAlertControllerStyleAlert];


UIAlertAction *defaultAction = [UIAlertAction actionWithTitle: cancelButtonTitle style: UIAlertActionStyleCancel handler: nil];

[alert addAction: defaultAction];

UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
[rootViewController presentViewController:alert animated:YES completion:nil];

Ora voglio cambiare titolo e carattere del messaggio, colore, dimensione e così via. Qual è il modo migliore per farlo?

Modifica: dovrei inserire l'intero codice. Ho creato una categoria per UIView che potrei mostrare l'avviso giusto per la versione iOS.

@implementation UIView (AlertCompatibility)

+( void )showSimpleAlertWithTitle:( NSString * )title
                          message:( NSString * )message
                cancelButtonTitle:( NSString * )cancelButtonTitle
{
    float iOSVersion = [[UIDevice currentDevice].systemVersion floatValue];
    if (iOSVersion < 8.0f)
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle: title
                                                        message: message
                                                       delegate: nil
                                              cancelButtonTitle: cancelButtonTitle
                                              otherButtonTitles: nil];
        [alert show];
    }
    else
    {
        // nil titles break alert interface on iOS 8.0, so we'll be using empty strings
        UIAlertController *alert = [UIAlertController alertControllerWithTitle: title == nil ? @"": title
                                                                       message: message
                                                                preferredStyle: UIAlertControllerStyleAlert];


        UIAlertAction *defaultAction = [UIAlertAction actionWithTitle: cancelButtonTitle
                                                                style: UIAlertActionStyleCancel
                                                              handler: nil];

        [alert addAction: defaultAction];

        UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
        [rootViewController presentViewController:alert animated:YES completion:nil];
    }
}

2
DISCLAIMER:A chiunque stia leggendo le risposte seguenti. Apple rifiuterà le tue app. Se tendi a utilizzare una o più API private. E nelle risposte seguenti ECCO CHE SUCCEDE ..
Yash Bedi

Risposte:


98

Non sono sicuro che ciò sia contro API / proprietà private, ma l'utilizzo di KVC funziona per me su iOS8

UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"Dont care what goes here, since we're about to change below" message:@"" preferredStyle:UIAlertControllerStyleActionSheet];
NSMutableAttributedString *hogan = [[NSMutableAttributedString alloc] initWithString:@"Presenting the great... Hulk Hogan!"];
[hogan addAttribute:NSFontAttributeName
              value:[UIFont systemFontOfSize:50.0]
              range:NSMakeRange(24, 11)];
[alertVC setValue:hogan forKey:@"attributedTitle"];



UIAlertAction *button = [UIAlertAction actionWithTitle:@"Label text" 
                                        style:UIAlertActionStyleDefault
                                        handler:^(UIAlertAction *action){
                                                    //add code to make something happen once tapped
}];
UIImage *accessoryImage = [UIImage imageNamed:@"someImage"];
[button setValue:accessoryImage forKey:@"image"];

Per la cronaca, è possibile modificare anche il carattere dell'azione di avviso, utilizzando tali API private. Ancora una volta, potrebbe farti rifiutare l'app, non ho ancora provato a inviare tale codice.

let alert = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet)

let action = UIAlertAction(title: "Some title", style: .Default, handler: nil)
let attributedText = NSMutableAttributedString(string: "Some title")

let range = NSRange(location: 0, length: attributedText.length)
attributedText.addAttribute(NSKernAttributeName, value: 1.5, range: range)
attributedText.addAttribute(NSFontAttributeName, value: UIFont(name: "ProximaNova-Semibold", size: 20.0)!, range: range)

alert.addAction(action)

presentViewController(alert, animated: true, completion: nil)

// this has to be set after presenting the alert, otherwise the internal property __representer is nil
guard let label = action.valueForKey("__representer")?.valueForKey("label") as? UILabel else { return }
label.attributedText = attributedText

Per Swift 4.2 in XCode 10 e versioni successive le ultime 2 righe sono ora:

guard let label = (action!.value(forKey: "__representer")as? NSObject)?.value(forKey: "label") as? UILabel else { return }
        label.attributedText = attributedText

6
Sta funzionando. attributedTitleper titolo e attributedMessageper messaggio. Non sono sicuro che sia la soluzione migliore, ma per ora è abbastanza buono per me.
Libor Zapletal

2
quali personalizzazioni possiamo aggiungere ai pulsanti UIAlertController ??
Aanchal Chaurasia,

1
Grazie! Ho una piccola domanda: si potrebbero usare caratteri e colori personalizzati con il riquadro dell'attributo e il messaggio in UIAlertController. Come si può fare lo stesso con UIAlertAction?
p0lAris

72
Spero che nessuno di voi stia pianificando di rilasciarlo nell'app store poiché utilizza API private. Seriamente, non ho idea del motivo per cui queste risposte siano mai accettate su Stackoverflow quando non sono realmente "risposte". Questi sono hack che potresti o meno farla franca con la pubblicazione nell'archivio applicazioni.
TheCodingArt

3
In caso di rilascio di app su app store, alcuni degli usi privati ​​delle API sono consentiti da Apple, ma non dovrebbe utilizzare le API che potrebbero danneggiare o influenzare il sistema / la privacy dell'utente. Quindi, probabilmente questa risposta potrebbe essere accettata da molte persone solo per questo. E probabilmente potrebbe non influire sull'app store. Qualcuno che l'ha usato può confermare che la sua app non è stata rifiutata?
Mehul Thakkar

66

È possibile modificare il colore del pulsante applicando un colore di tinta a un UIAlertController.

Su iOS 9, se il colore della tinta della finestra era impostato su un colore personalizzato, è necessario applicare il colore della tinta subito dopo aver presentato l'avviso. In caso contrario, il colore della tinta verrà reimpostato sul colore della tinta della finestra personalizzato.

// In your AppDelegate for example:
window?.tintColor = UIColor.redColor()

// Elsewhere in the App:
let alertVC = UIAlertController(title: "Title", message: "message", preferredStyle: .Alert)
alertVC.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: nil))
alertVC.addAction(UIAlertAction(title: "Ok", style: .Default, handler: nil))

// Works on iOS 8, but not on iOS 9
// On iOS 9 the button color will be red
alertVC.view.tintColor = UIColor.greenColor()

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

// Necessary to apply tint on iOS 9
alertVC.view.tintColor = UIColor.greenColor()

20
Per chiarire, l'impostazione di tintColor dopo aver presentato il controller funziona sia su iOS 8 che su 9, quindi non è necessario impostarlo due volte.
arlomedia

Grazie per aver aggiunto una risposta rapida e una soluzione alternativa per questo problema in iOS 9.
peacetype

3
Quando tocco e trascino il dito verso il basso, tornerà al colore predefinito. Qualche idea?
msmq

Questa è davvero l'unica risposta decente qui.
TheCodingArt

47

Puoi cambiare il colore del testo del pulsante usando questo codice:

alertC.view.tintColor = your color;

Forse questo ti aiuterà.


@esilver sei riuscito a trovare una soluzione che funziona con iOS9?
Ash

1
Io non. Ho creato una segnalazione di bug con Apple, # 22391695.
esilver

1
Maggiori informazioni su questo. Sembra che quando scorri una lunga lista di voci, quella che tocchi per scorrere diventa blu ...
Bejil

3
Niente di tutto questo funziona su UIAlertController in iOS9 e 9.1 .. Non so cosa stanno facendo i ragazzi di Apple ... È necessario modificare manualmente la tinta della finestra ogni volta che viene chiamato un controller di avviso e cambiarlo nuovamente nel gestore.
Akhilesh Sharma,

Funziona con iOS 9.3, a meno che tu non ritocchi all'esterno: torna al blu di sistema
Rémi Belzanti

35

In Xcode 8 Swift 3.0

@IBAction func touchUpInside(_ sender: UIButton) {

    let alertController = UIAlertController(title: "", message: "", preferredStyle: .alert)

    //to change font of title and message.
    let titleFont = [NSFontAttributeName: UIFont(name: "ArialHebrew-Bold", size: 18.0)!]
    let messageFont = [NSFontAttributeName: UIFont(name: "Avenir-Roman", size: 12.0)!]

    let titleAttrString = NSMutableAttributedString(string: "Title Here", attributes: titleFont)
    let messageAttrString = NSMutableAttributedString(string: "Message Here", attributes: messageFont)

    alertController.setValue(titleAttrString, forKey: "attributedTitle")
    alertController.setValue(messageAttrString, forKey: "attributedMessage")

    let action1 = UIAlertAction(title: "Action 1", style: .default) { (action) in
        print("\(action.title)")
    }

    let action2 = UIAlertAction(title: "Action 2", style: .default) { (action) in
        print("\(action.title)")
    }

    let action3 = UIAlertAction(title: "Action 3", style: .default) { (action) in
        print("\(action.title)")
    }

    let okAction = UIAlertAction(title: "Ok", style: .default) { (action) in
        print("\(action.title)")
    }

    alertController.addAction(action1)
    alertController.addAction(action2)
    alertController.addAction(action3)
    alertController.addAction(okAction)

    alertController.view.tintColor = UIColor.blue
    alertController.view.backgroundColor = UIColor.black
    alertController.view.layer.cornerRadius = 40

    present(alertController, animated: true, completion: nil)

}

Produzione

Carattere, dimensione e colore personalizzati di UIAlertController


Scusa fratello, questo è avviato. Se richiesto nella funzionalità ti informerò ...
iOS

24

Una traduzione rapida della risposta @ dupuis2387. Ha elaborato la sintassi per impostare il UIAlertControllercolore e il carattere del titolo tramite KVC utilizzando il attributedTitletasto.

let message = "Some message goes here."
let alertController = UIAlertController(
    title: "", // This gets overridden below.
    message: message,
    preferredStyle: .Alert
)
let okAction = UIAlertAction(title: "OK", style: .Cancel) { _ -> Void in
}
alertController.addAction(okAction)

let fontAwesomeHeart = "\u{f004}"
let fontAwesomeFont = UIFont(name: "FontAwesome", size: 17)!
let customTitle:NSString = "I \(fontAwesomeHeart) Swift" // Use NSString, which lets you call rangeOfString()
let systemBoldAttributes:[String : AnyObject] = [ 
    // setting the attributed title wipes out the default bold font,
    // so we need to reconstruct it.
    NSFontAttributeName : UIFont.boldSystemFontOfSize(17)
]
let attributedString = NSMutableAttributedString(string: customTitle as String, attributes:systemBoldAttributes)
let fontAwesomeAttributes = [
    NSFontAttributeName: fontAwesomeFont,
    NSForegroundColorAttributeName : UIColor.redColor()
]
let matchRange = customTitle.rangeOfString(fontAwesomeHeart)
attributedString.addAttributes(fontAwesomeAttributes, range: matchRange)
alertController.setValue(attributedString, forKey: "attributedTitle")

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

inserisci qui la descrizione dell'immagine


3
E il pulsante "OK"? Possiamo personalizzarlo?
Hassan Taleb

@ HassanTaleb Non ho trovato un ottimo modo per personalizzare il pulsante. Puoi impostare tintColorsu viewo tramite appearanceWhenContainedIn, ma la tinta scompare non appena la tocchi. Tuttavia, sto ancora cercando risposte.
Robert Chen

@AbdulMomen عبدالمؤمن Quale messaggio di errore visualizzi? Lo snippet di codice presuppone che FontAwesome sia già impostato.
Robert Chen

1
@RobertChen per risolvere il problema basta mettere la tinta dopo:, self.presentViewController(alertController, animated: true, completion: nil)possiamo cambiare il carattere del pulsante "OK"?
Hassan Taleb

4
Non è considerata un'API privata?
Jinghan Wang

13

Usa il UIAppearanceprotocollo. Esempio per l'impostazione di un carattere: crea una categoria da estendere UILabel:

@interface UILabel (FontAppearance)
@property (nonatomic, copy) UIFont * appearanceFont UI_APPEARANCE_SELECTOR;
@end


@implementation UILabel (FontAppearance)

-(void)setAppearanceFont:(UIFont *)font {
    if (font)
        [self setFont:font];
}

-(UIFont *)appearanceFont {
    return self.font;
}

@end

E il suo utilizzo:

UILabel * appearanceLabel = [UILabel appearanceWhenContainedIn:UIAlertController.class, nil];
[appearanceLabel setAppearanceFont:[UIFont boldSystemFontOfSize:10]]; //for example

Testato e funzionante con stile UIAlertControllerStyleActionSheet, ma credo che funzionerà UIAlertControllerStyleAlertanche con .

PS Controlla meglio la disponibilità delle classi invece della versione iOS:

if ([UIAlertController class]) {
    // UIAlertController code (iOS 8)
} else {
    // UIAlertView code (pre iOS 8)
}

Funziona ma in questo modo non posso avere dimensioni diverse per il messaggio e per il titolo.
Libor Zapletal

Funziona, ma quando si fa clic su un'azione, il carattere torna alla dimensione originale? Ti succede questo?
Larry

Ho lo stesso problema @ Larry e non ho trovato un modo per risolverlo .. vero?
alasker

12

Usa il UIAppearanceprotocollo. Fai più hack con appearanceFontper cambiare il carattere per UIAlertAction.

Crea una categoria per UILabel

UILabel + FontAppearance.h

@interface UILabel (FontAppearance)

@property (nonatomic, copy) UIFont * appearanceFont UI_APPEARANCE_SELECTOR;

@end

UILabel + FontAppearance.m

@implementation UILabel (FontAppearance)

- (void)setAppearanceFont:(UIFont *)font
{
    if (self.tag == 1001) {
        return;
    }

    BOOL isBold = (self.font.fontDescriptor.symbolicTraits & UIFontDescriptorTraitBold);
    const CGFloat* colors = CGColorGetComponents(self.textColor.CGColor);

    if (self.font.pointSize == 14) {
        // set font for UIAlertController title
        self.font = [UIFont systemFontOfSize:11];
    } else if (self.font.pointSize == 13) {
        // set font for UIAlertController message
        self.font = [UIFont systemFontOfSize:11];
    } else if (isBold) {
        // set font for UIAlertAction with UIAlertActionStyleCancel
        self.font = [UIFont systemFontOfSize:12];
    } else if ((*colors) == 1) {
        // set font for UIAlertAction with UIAlertActionStyleDestructive
        self.font = [UIFont systemFontOfSize:13];
    } else {
        // set font for UIAlertAction with UIAlertActionStyleDefault
        self.font = [UIFont systemFontOfSize:14];
    }
    self.tag = 1001;
}

- (UIFont *)appearanceFont
{
    return self.font;
}

@end

Uso:

Inserisci

[[UILabel appearanceWhenContainedIn:UIAlertController.class, nil] setAppearanceFont:nil];

in AppDelegate.mper farlo funzionare per tutti UIAlertController.


Il titolo in iOS 8.3 è 13pt e in grassetto, quindi ho cambiato la condizione inif (self.font.pointSize == 13 && isBold) {
Andrew Raphael

Hai accennato a cambiare il carattere per UIAlertAction. Ma per quanto ne so, UIAlertActionnon usa un file UILabel. Utilizza un file NSString. github.com/nst/iOS-Runtime-Headers/blob/… Non so come potresti personalizzare il carattere per un file NSString.
peacetype

UIAlertAction non è affatto una classe di visualizzazione. È una classe astratta che descrive l'azione. La vista stessa viene quindi generata all'interno di UIAlertController. Si imposta quindi l'aspetto contenuto in UIAlertController.
mangerlahn

12

Swift 5 e 5.1 . Crea un file separato e inserisci il codice di personalizzazione UIAlertController lì

import Foundation
import  UIKit

extension UIAlertController {

  //Set background color of UIAlertController
  func setBackgroudColor(color: UIColor) {
    if let bgView = self.view.subviews.first,
      let groupView = bgView.subviews.first,
      let contentView = groupView.subviews.first {
      contentView.backgroundColor = color
    }
  }

  //Set title font and title color
  func setTitle(font: UIFont?, color: UIColor?) {
    guard let title = self.title else { return }
    let attributeString = NSMutableAttributedString(string: title)//1
    if let titleFont = font {
      attributeString.addAttributes([NSAttributedString.Key.font : titleFont],//2
        range: NSMakeRange(0, title.utf8.count))
    }
    if let titleColor = color {
      attributeString.addAttributes([NSAttributedString.Key.foregroundColor : titleColor],//3
        range: NSMakeRange(0, title.utf8.count))
    }
    self.setValue(attributeString, forKey: "attributedTitle")//4
  }

  //Set message font and message color
  func setMessage(font: UIFont?, color: UIColor?) {
    guard let title = self.message else {
      return
    }
    let attributedString = NSMutableAttributedString(string: title)
    if let titleFont = font {
      attributedString.addAttributes([NSAttributedString.Key.font : titleFont], range: NSMakeRange(0, title.utf8.count))
    }
    if let titleColor = color {
      attributedString.addAttributes([NSAttributedString.Key.foregroundColor : titleColor], range: NSMakeRange(0, title.utf8.count))
    }
    self.setValue(attributedString, forKey: "attributedMessage")//4
  }

  //Set tint color of UIAlertController
  func setTint(color: UIColor) {
    self.view.tintColor = color
  }
}

Ora su qualsiasi azione Mostra avviso

  func tapShowAlert(sender: UIButton) {
    let alertController = UIAlertController(title: "Alert!!", message: "This is custom alert message", preferredStyle: .alert)
    // Change font and color of title
    alertController.setTitle(font: UIFont.boldSystemFont(ofSize: 26), color: UIColor.yellow)
    // Change font and color of message
    alertController.setMessage(font: UIFont(name: "AvenirNextCondensed-HeavyItalic", size: 18), color: UIColor.red)
    // Change background color of UIAlertController
    alertController.setBackgroudColor(color: UIColor.black)
    let actnOk = UIAlertAction(title: "Ok", style: .default, handler: nil)
    let actnCancel = UIAlertAction(title: "Cancel", style: .default, handler: nil)
    alertController.addAction(actnOk)
    alertController.addAction(actnCancel)
    self.present(alertController, animated: true, completion: nil)
  }

Risultato

inserisci qui la descrizione dell'immagine


1
stiamo accedendo a qualche API privata qui? hai rilasciato un'app con queste numerose proprietà di avviso personalizzate?
Yash Bedi,

@YashBedi utilizza API private e Apple potrebbe rifiutare la tua app per l'utilizzo di "API non pubbliche". No, non ho rilasciato alcuna app.
Gurjinder Singh

Questo è menzionato nel sito per sviluppatori Apple -> Importante La classe UIAlertController deve essere utilizzata così com'è e non supporta la creazione di sottoclassi. La gerarchia di visualizzazione per questa classe è privata e non deve essere modificata.
Gurjinder Singh

Capito Boss Grazie.
Yash Bedi,

@ Darkglow Si prega di menzionare l'errore. Sono in grado di creare con successo lo stesso codice con swift 5.1
Gurjinder Singh

10

Lo sto usando.

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

Aggiungi una riga (AppDelegate) e funziona per tutti gli UIAlertController.


3
Poiché ora è deprecato, utilizzare [[UIView aspectWhenContainedInInstancesOfClasses: @ [[UIAlertController class]]] setTintColor: newColor]; invece
Peter Johnson

8

Swift 4

Esempio di carattere personalizzato sul titolo. Stesse cose per altri componenti come messaggi o azioni.

    let titleAttributed = NSMutableAttributedString(
            string: Constant.Strings.cancelAbsence, 
            attributes: [NSAttributedStringKey.font:UIFont(name:"FONT_NAME",size: FONT_SIZE)]
    )

    let alertController = UIAlertController(
        title: "",
        message: "",
        preferredStyle: UIAlertControllerStyle.YOUR_STYLE
    )

    alertController.setValue(titleAttributed, forKey : "attributedTitle")
    present(alertController, animated: true, completion: nil)

5

Ecco un'estensione per Swift 4.1 e Xcode 9.4.1:

extension UIAlertController{

func addColorInTitleAndMessage(color:UIColor,titleFontSize:CGFloat = 18, messageFontSize:CGFloat = 13){

    let attributesTitle = [NSAttributedStringKey.foregroundColor: color, NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: titleFontSize)]
    let attributesMessage = [NSAttributedStringKey.foregroundColor: color, NSAttributedStringKey.font: UIFont.systemFont(ofSize: messageFontSize)]
    let attributedTitleText = NSAttributedString(string: self.title ?? "", attributes: attributesTitle)
    let attributedMessageText = NSAttributedString(string: self.message ?? "", attributes: attributesMessage)

    self.setValue(attributedTitleText, forKey: "attributedTitle")
    self.setValue(attributedMessageText, forKey: "attributedMessage")

}}

4

Ho appena completato una sostituzione per UIAlertController. Questo è l'unico modo sensato per andare, penso:


Vecchio

Ecco il mio metodo in Swift che combina molte informazioni dalle risposte qui

func changeAlert(alert: UIAlertController, backgroundColor: UIColor, textColor: UIColor, buttonColor: UIColor?) {
    let view = alert.view.firstSubview().firstSubview()
    view.backgroundColor = backgroundColor
    view.layer.cornerRadius = 10.0

    // set color to UILabel font
    setSubviewLabelsToTextColor(textColor, view: view)

    // set font to alert via KVC, otherwise it'll get overwritten
    let titleAttributed = NSMutableAttributedString(
        string: alert.title!,
        attributes: [NSFontAttributeName:UIFont.boldSystemFontOfSize(17)])
    alert.setValue(titleAttributed, forKey: "attributedTitle")


    let messageAttributed = NSMutableAttributedString(
        string: alert.message!,
        attributes: [NSFontAttributeName:UIFont.systemFontOfSize(13)])
    alert.setValue(messageAttributed, forKey: "attributedMessage")


    // set the buttons to non-blue, if we have buttons
    if let buttonColor = buttonColor {
        alert.view.tintColor = buttonColor
    }
}

func setSubviewLabelsToTextColor(textColor: UIColor, view:UIView) {
    for subview in view.subviews {
        if let label = subview as? UILabel {
            label.textColor = textColor
        } else {
            setSubviewLabelsToTextColor(textColor, view: subview)
        }
    }
}

Funziona perfettamente in alcune situazioni e in altre è un fallimento totale (i colori della tinta non vengono visualizzati come previsto).


4

Puoi utilizzare una libreria esterna come PMAlertController senza utilizzare soluzioni alternative, in cui puoi sostituire l'UIAlertController non personalizzabile di Apple con un avviso super personalizzabile.

Compatibile con Xcode 8, Swift 3 e Objective-C

Esempio di PMAlertController


Caratteristiche:

  • [x] Visualizzazione intestazione
  • [x] Immagine intestazione (facoltativa)
  • [x] Titolo
  • [x] Messaggio di descrizione
  • [x] Personalizzazioni: caratteri, colori, dimensioni e altro
  • [x] 1, 2 pulsanti (orizzontalmente) o 3+ pulsanti (verticalmente)
  • [x] Chiusura alla pressione di un pulsante
  • [x] Supporto per campi di testo
  • [x] Implementazione simile a UIAlertController
  • [x] Cocoapods
  • [x] Cartagine
  • [x] Animazione con UIKit Dynamics
  • [x] Compatibilità Objective-C
  • [x] Supporto per Swift 2.3 e Swift 3

PMAlertController consente il ritorno a capo automatico quando il testo è lungo nei pulsanti di azione?
Zeeple

@zeeple considera che il pulsante di azione è una sottoclasse di UIButton. Qualcosa del genere actionButton.titleLabel.lineBreakMode = NSLineBreakByWordWrappingfunziona bene.
Paolo Musolino

3

C'è un problema con l'impostazione del colore della tinta sulla vista dopo la presentazione; anche se lo fai nel blocco di completamento di presentViewController: animated: completamento :, provoca uno sfarfallio sul colore dei titoli dei pulsanti. Questo è sciatto, poco professionale e completamente inaccettabile.

Altre soluzioni presentate dipendono dal fatto che la gerarchia della visualizzazione rimanga statica, qualcosa che Apple non sopporta di fare. Aspettatevi che queste soluzioni falliscano nelle versioni future di iOS.

L'unico modo sicuro per risolvere questo problema e farlo ovunque, è aggiungere una categoria a UIAlertController e far scorrere il viewWillAppear.

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'implemento:

//
//  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

Aggiungi un .pch (intestazione precompilata) al tuo progetto e includi la categoria:

#import "UIAlertController+iOS9TintFix.h"

Assicurati di registrare correttamente il tuo pch nel progetto e includerà i metodi di categoria in ogni classe che utilizza UIAlertController.

Quindi, nel metodo didFinishLaunchingWithOptions dei delegati dell'app, importa la categoria e chiama

[UIAlertController tintFix];

e si propagherà automaticamente a ogni singola istanza di UIAlertController all'interno della tua app, sia lanciata dal tuo codice che da chiunque altro.

Questa soluzione funziona sia per iOS 8.X che per iOS 9.X e manca dello sfarfallio dell'approccio post-presentazione del cambio di tinta. È anche completamente agnostico rispetto alla gerarchia di visualizzazione delle viste secondarie di UIAlertController.

Buon hacking!


Questa soluzione funziona, principalmente. Sul dispositivo ruotano, tuttavia, le tinte tornano a come erano, prima dello swizzling.
Dhiraj Gupta

Dhiraj, l'ho appena testato di nuovo in una configurazione di progetto esplicitamente per esplorare le tue scoperte, e non sono d'accordo. La tinta non torna come era durante la rotazione.
ObiDan

Funzionalità verificata su xcode 6.4 e xcode 7.0. Esecuzione di simulatori di tutte le varianti di 8.X e 9.0. Se richiesto, inserirò il progetto su GitHub.
ObiDan

Beh, potresti andare avanti e mettere su un progetto, ma questo è quello che stavo vedendo accadermi. Inoltre non funzionava su iPad. Sulla base della sua idea metodo swizzling, però, mi ero in grado di farlo funzionare da viewDidLayoutSubviews swizzling, però.
Dhiraj Gupta

Se proponi un progetto, allora potrei inviare una richiesta pull con viewDidLayoutSubviews swizzle, che è quello che ho appena usato e inviato nell'ultima build della mia app all'App Store e puoi dare un'occhiata, forse?
Dhiraj Gupta

3

Trova questa categoria. Sono in grado di cambiare FONT e Colore di UIAlertAction e UIAlertController.

Uso:

UILabel * appearanceLabel = [UILabel appearanceWhenContainedIn:UIAlertController.class, nil];
[appearanceLabel setAppearanceFont:yourDesireFont]];  

5
Per favore, incolla il codice qui o utilizza un servizio che non richiede l'accesso da parte delle persone.
Sulthan

3

In Swift 4.1 e Xcode 10

//Displaying alert with multiple actions and custom font ans size
let alert = UIAlertController(title: "", message: "", preferredStyle: .alert)

let titFont = [NSAttributedStringKey.font: UIFont(name: "ArialHebrew-Bold", size: 15.0)!]
let msgFont = [NSAttributedStringKey.font: UIFont(name: "Avenir-Roman", size: 13.0)!]

let titAttrString = NSMutableAttributedString(string: "Title Here", attributes: titFont)
let msgAttrString = NSMutableAttributedString(string: "Message Here", attributes: msgFont)

alert.setValue(titAttrString, forKey: "attributedTitle")
alert.setValue(msgAttrString, forKey: "attributedMessage")

let action1 = UIAlertAction(title: "Action 1", style: .default) { (action) in
    print("\(String(describing: action.title))")
}

let action2 = UIAlertAction(title: "Action 2", style: .default) { (action) in
    print("\(String(describing: action.title))")
}

let okAction = UIAlertAction(title: "Ok", style: .default) { (action) in
    print("\(String(describing: action.title))")
}
alert.addAction(action1)
alert.addAction(action2)
alert.addAction(okAction)

alert.view.tintColor = UIColor.blue
alert.view.layer.cornerRadius = 40
// //If required background colour 
// alert.view.backgroundColor = UIColor.white

DispatchQueue.main.async(execute: {
    self.present(alert, animated: true)
})

la tua risposta necessita di un aggiornamento, self.present(alertController, animated: true)o self.present(alert, animated: true).
Yash Bedi,

@ Yash Bedi, grazie ho aggiornato la mia risposta, per favore controllala una volta.
iOS

2

Soluzione / Hack per iOS9

    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Test Error" message:@"This is a test" preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
        NSLog(@"Alert View Displayed");
 [[[[UIApplication sharedApplication] delegate] window] setTintColor:[UIColor whiteColor]];
    }];

    [alertController addAction:cancelAction];
    [[[[UIApplication sharedApplication] delegate] window] setTintColor:[UIColor blackColor]];
    [self presentViewController:alertController animated:YES completion:^{
        NSLog(@"View Controller Displayed");
    }];

Ho provato questo. Tieni presente che stai ripristinando l'impostazione della tonalità della finestra una volta visualizzato il controller degli avvisi. Vedo il colore che cambia di nuovo direttamente sul controller degli avvisi. Credo che la riverenza debba essere eseguita una volta che qualsiasi azione è stata sfruttata.
Germania

Grazie @ Germán per averlo sottolineato .. Apportato le modifiche al codice. Sto gestendo il ripristino in AlertAction fin da ora .. Ma sì, sono d'accordo che può essere gestito anche nel gestore dimiss
Akhilesh Sharma

1

Lavoro per Urban Outfitters. Abbiamo un pod open source URBNAlert, che abbiamo utilizzato in tutte le nostre app. È basato su UIAlertController, ma è altamente personalizzabile.

La fonte è qui: https://github.com/urbn/URBNAlert

O semplicemente installalo dal pod inserendolo URBNAlertnel tuo Podfile

Ecco alcuni esempi di codice:

URBNAlertViewController *uac = [[URBNAlertViewController alloc] initWithTitle:@"The Title of my message can be up to 2 lines long. It wraps and centers." message:@"And the message that is a bunch of text. And the message that is a bunch of text. And the message that is a bunch of text."];

// You can customize style elements per alert as well. These will override the global style just for this alert.
uac.alertStyler.blurTintColor = [[UIColor orangeColor] colorWithAlphaComponent:0.4];
uac.alertStyler.backgroundColor = [UIColor orangeColor];
uac.alertStyler.textFieldEdgeInsets = UIEdgeInsetsMake(0.0, 15.0, 0.0, 15.0);
uac.alertStyler.titleColor = [UIColor purpleColor];
uac.alertStyler.titleFont = [UIFont fontWithName:@"Chalkduster" size:30];
uac.alertStyler.messageColor = [UIColor blackColor];
uac.alertStyler.alertMinWidth = @150;
uac.alertStyler.alertMaxWidth = @200;
// many more styling options available 

[uac addAction:[URBNAlertAction actionWithTitle:@"Ok" actionType:URBNAlertActionTypeNormal actionCompleted:^(URBNAlertAction *action) {
      // Do something
}]];

[uac addAction:[URBNAlertAction actionWithTitle:@"Cancel" actionType:URBNAlertActionTypeCancel actionCompleted:^(URBNAlertAction *action) {
      // Do something
}]];

[uac show];

Questo supporta lo stile ActionSheet?
Danpe

@ Danpe non lo fa, è puramente solo per avvisi .. Detto questo .. se è qualcosa che desideri creare un problema sul repo. Questo è qualcosa per cui abbiamo discusso l'aggiunta del supporto prima
RyanG

1

Per cambiare il colore di un pulsante come CANCEL con il colore rosso puoi usare questa proprietà di stile chiamata UIAlertActionStyle.destructive:

let prompt = UIAlertController.init(title: "Reset Password", message: "Enter Your E-mail :", preferredStyle: .alert)
        let okAction = UIAlertAction.init(title: "Submit", style: .default) { (action) in
              //your code
}

let cancelAction = UIAlertAction.init(title: "Cancel", style: UIAlertActionStyle.destructive) { (action) in
                //your code
        }
        prompt.addTextField(configurationHandler: nil)
        prompt.addAction(okAction)
        prompt.addAction(cancelAction)
        present(prompt, animated: true, completion: nil);

1

Per iOS 9.0 e versioni successive, usa questo codice nel delegato dell'app

[[UIView appearanceWhenContainedInInstancesOfClasses:@[[UIAlertController class]]] setTintColor:[UIColor redColor]];

1

Swift 5.0

let titleAttrString = NSMutableAttributedString(string: "This is a title", attributes: [NSAttributedString.Key.font: UIFont(name: "CustomFontName", size: 17) as Any])
let messageAttrString = NSMutableAttributedString(string: "This is a message", attributes: [NSAttributedString.Key.font: UIFont(name: "CustomFontName", size: 13) as Any])

alertController.setValue(titleAttrString, forKey: "attributedTitle")
alertController.setValue(messageAttrString, forKey: "attributedMessage")

0

Un po 'goffo, ma ora funziona per me per impostare i colori dello sfondo e del testo. L'ho trovato qui .

UIView * firstView = alertController.view.subviews.firstObject;
    UIView * nextView = firstView.subviews.firstObject;
    nextView.backgroundColor = [UIColor blackColor];

Funziona per il colore di sfondo ma non cambia mai il colore della tinta, questo è ciò di cui sono un po 'confuso
Akhilesh Sharma,

0

Ho creato un metodo obiettivo-C

-(void)customAlertTitle:(NSString*)title message:(NSString*)message{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:nil delegate:nil cancelButtonTitle:@"NO" otherButtonTitles:@"YES", nil];
UIView *subView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 80)];

UILabel *titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 270, 50)];
titleLabel.text = title;
titleLabel.font = [UIFont boldSystemFontOfSize:20];
titleLabel.numberOfLines = 2;
titleLabel.textColor = [UIColor redColor];
titleLabel.textAlignment = NSTextAlignmentCenter;

[subView addSubview:titleLabel];

UILabel *messageLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 30, 270, 50)];
messageLabel.text = message;
messageLabel.font = [UIFont systemFontOfSize:18];
messageLabel.numberOfLines = 2;
messageLabel.textColor = [UIColor redColor];
messageLabel.textAlignment = NSTextAlignmentCenter;

[subView addSubview:messageLabel];

[alertView setValue:subView forKey:@"accessoryView"];
[alertView show];
}

Il codice funziona perfettamente su Xcode 8.3.1. È possibile personalizzare in base alle esigenze.


0

Uso solo questo tipo di richiesta, apparentemente e sistema, i dettagli sono leggermente diversi, quindi siamo ... OC ha realizzato l'incapsulamento della finestra popup di avviso e foglio.

Spesso incontrata nella necessità di sviluppo quotidiano di aggiungere una cifra ad Alert o cambiare il colore di un pulsante, come la richiesta "semplice", oggi porta un e componenti di sistema molto simili e possono soddisfare pienamente la domanda di componenti di imballaggio personalizzati.

Github: https://github.com/ReverseScale/RSCustomAlertView

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.