Fonte, tamanho e cor personalizados do UIAlertController

118

Estou usando o novo UIAlertController para mostrar alertas. Eu tenho este código:

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

Agora eu quero mudar o título e a fonte da mensagem, cor, tamanho e assim. Qual é a melhor maneira de fazer isso?

Edit: devo inserir o código inteiro. Criei categoria para UIView que poderia mostrar alerta certo para versão 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];
    }
}
Libor Zapletal
fonte
2
DISCLAIMER:Para quem está lendo as respostas abaixo. A Apple rejeitará seu (s) aplicativo (s). Se você tende a usar qualquer Api (s) privado (s). E nas respostas abaixo ISSO É O QUE ESTÁ ACONTECENDO ..
Yash Bedi

Respostas:

98

Não tenho certeza se isso é contra APIs / propriedades privadas, mas usar KVC funciona para mim no 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"];

Para registro, é possível alterar a fonte da ação de alerta também, usando essas APIs privadas. Novamente, isso pode fazer com que seu aplicativo seja rejeitado. Ainda não tentei enviar esse código.

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

Para Swift 4.2 em XCode 10 e superior, as últimas 2 linhas são agora:

guard let label = (action!.value(forKey: "__representer")as? NSObject)?.value(forKey: "label") as? UILabel else { return }
        label.attributedText = attributedText
dupuis2387
fonte
6
Está funcionando. attributedTitlepara título e attributedMessagepara mensagem. Não tenho certeza se é a melhor solução, mas por enquanto é bom o suficiente para mim.
Libor Zapletal
2
qual personalização podemos adicionar nos botões do UIAlertController ??
Aanchal Chaurasia
1
Obrigado! Eu tenho uma pequena dúvida - alguém poderia usar fontes e cores personalizadas com o atributo tile e mensagem em UIAlertController. Como fazer o mesmo com UIAlertAction?
p0lAris de
72
Espero que nenhum de vocês esteja planejando lançar isso na app store, pois usa APIs privadas. Sério, não tenho ideia de por que essas respostas são aceitas no Stackoverflow quando na verdade não são 'respostas'. Esses são hacks que você pode ou não conseguir publicar na loja de aplicativos.
TheCodingArt
3
Para o caso de lançamento de aplicativo na app store, alguns dos usos de api privados são permitidos pela Apple, mas não deve usar a apis que pode prejudicar ou afetar o sistema / privacidade do usuário. Portanto, provavelmente esta resposta pode ser aceita por muitas pessoas devido apenas a isso. E provavelmente pode não estar afetando na app store. Alguém que já usou isso pode confirmar que seu aplicativo não foi rejeitado?
Mehul Thakkar
66

Você pode alterar a cor do botão aplicando uma cor de matiz a um UIAlertController.

No iOS 9, se a cor da tonalidade da janela foi definida como uma cor personalizada, você deve aplicar a cor da tonalidade logo após apresentar o alerta. Caso contrário, a cor da tonalidade será redefinida para a cor de tonalidade da janela personalizada.

// 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()
Macucula
fonte
20
Para esclarecer, configurar o tintColor após apresentar o controlador funciona no iOS 8 e 9, portanto, não é necessário configurá-lo duas vezes.
arlomedia
Obrigado por adicionar uma resposta
rápida
3
Quando toco e arrasto meu dedo para baixo, ele volta para a cor padrão. Qualquer ideia?
msmq de
Esta é realmente a única resposta decente aqui.
TheCodingArt
47

Você pode alterar a cor do texto do botão usando este código:

alertC.view.tintColor = your color;

Talvez isso ajude você.

ChintaN -Maddy- Ramani
fonte
@esilver você conseguiu encontrar uma solução que funcione com iOS9?
Cinza
1
Eu não. Criei um relatório de bug com a Apple, # 22391695.
esilver
1
Mais informações sobre isso. Parece que quando você rola em uma longa lista de itens, aquele que você toca para rolar fica azul ...
Bejil
3
Nada disso funciona no UIAlertController no iOS9 e 9.1 .. Não sei o que os caras da Apple estão fazendo ... Precisa alterar manualmente a tonalidade da janela toda vez que um controlador de alerta é chamado e alterá-lo de volta no manipulador.
Akhilesh Sharma
Funciona com o iOS 9.3, a menos que você
retome o lado externo
35

No 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)

}

Resultado

Fonte, tamanho e cor personalizados do UIAlertController

Ashok R
fonte
Desculpe mano, isso é inicial. Se necessário, o recurso informarei a você ...
iOS
24

Uma tradução rápida da resposta @ dupuis2387. Trabalhou a sintaxe para definir a UIAlertControllercor e fonte do título via KVC usando a attributedTitletecla.

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)

insira a descrição da imagem aqui

Robert Chen
fonte
3
E o botão "OK"? Podemos personalizá-lo?
Hassan Taleb
@HassanTaleb Não encontrei uma ótima maneira de personalizar o botão. Você pode definir tintColorno viewou via appearanceWhenContainedIn, mas a tonalidade desaparece assim que você toca. Ainda procurando por respostas.
Robert Chen,
@AbdulMomen عبدالمؤمن Que mensagem de erro você está vendo? O snippet de código assume que FontAwesome já está configurado.
Robert Chen,
1
@RobertChen para resolver o problema basta colocar a tonalidade depois:, self.presentViewController(alertController, animated: true, completion: nil)podemos mudar a fonte do botão "OK"?
Hassan Taleb
4
Isso não é considerado uma API privada?
Jinghan Wang,
13

Use UIAppearanceprotocolo. Exemplo para definir uma fonte - crie uma categoria para estender 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 seu uso:

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

Testado e trabalhando com estilo UIAlertControllerStyleActionSheet, mas acho que funcionará UIAlertControllerStyleAlerttambém.

PS Melhor verificar a disponibilidade das aulas em vez da versão iOS:

if ([UIAlertController class]) {
    // UIAlertController code (iOS 8)
} else {
    // UIAlertView code (pre iOS 8)
}
Ivan
fonte
Está funcionando, mas desta forma não posso ter tamanhos diferentes para a mensagem e para o título.
Libor Zapletal de
Isso funciona, mas quando uma ação é clicada, a fonte volta ao tamanho original? Isso acontece para você?
Larry,
Estou com o mesmo problema @Larry e não achei uma maneira de lidar com ele .. você encontrou?
Alaska
12

Use UIAppearanceprotocolo. Faça mais hacks com appearanceFontpara alterar a fonte UIAlertAction.

Crie uma categoria para 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:

adicionar

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

em AppDelegate.mfazê-lo funcionar para todos UIAlertController.

user3480295
fonte
O título no iOS 8.3 é 13pt e negrito, então mudei a condição paraif (self.font.pointSize == 13 && isBold) {
Andrew Raphael
Você mencionou mudar a fonte para UIAlertAction. Mas, pelo que posso dizer, UIAlertActionnão usa a UILabel. Ele usa um NSString. github.com/nst/iOS-Runtime-Headers/blob/… Não sei como você pode personalizar a fonte para um NSString.
peacetype
UIAlertAction não é uma classe de visualização. É uma classe abstrata que descreve a ação. A própria visão é então gerada dentro do UIAlertController. Portanto, você define a aparência contida em UIAlertController.
mangerlahn
12

Swift 5 e 5.1 . Crie um arquivo separado e coloque o código de personalização 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
  }
}

Agora em qualquer ação Mostrar alerta

  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)
  }

Resultado

insira a descrição da imagem aqui

Gurjinder Singh
fonte
1
estamos acessando alguma Api privada aqui.? você lançou algum aplicativo com essas muitas propriedades de alerta personalizadas?
Yash Bedi
@YashBedi está usando APIs privadas e a Apple pode rejeitar seu aplicativo para uso de "API não pública". Não, eu não lancei nenhum app.
Gurjinder Singh
Isso é mencionado no site de desenvolvedor da Apple -> Importante A classe UIAlertController deve ser usada no estado em que se encontra e não oferece suporte a subclasses. A hierarquia de visualização para esta classe é privada e não deve ser modificada.
Gurjinder Singh
Entendi, chefe. Obrigado.
Yash Bedi
@Darkglow Mencione o erro. Eu sou capaz de construir com sucesso o mesmo código com swift 5.1
Gurjinder Singh
10

Estou usando isso.

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

Adicione uma linha (AppDelegate) e funciona para todos os UIAlertController.

Lucas torquato
fonte
3
Como isso agora está obsoleto, use [[UIView appearWhenContainedInInstancesOfClasses: @ [[UIAlertController class]]] setTintColor: newColor]; em vez disso
Peter Johnson
8

Swift 4

Exemplo de fonte personalizada no título. As mesmas coisas para outros componentes, como mensagem ou ações.

    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)
AnthonyR
fonte
5

Aqui está uma extensão para 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")

}}
Vassilis A. Alexiou
fonte
4

Acabei de completar uma substituição para UIAlertController. Esta é a única maneira sensata de ir, eu acho:


Velho

Este é o meu método em Swift, que combina muitas informações das respostas aqui

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)
        }
    }
}

Isso funciona perfeitamente em algumas situações, e em outras é uma falha total (as cores de matiz não aparecem como o esperado).

Dan Rosenstark
fonte
4

Você pode usar uma biblioteca externa como PMAlertController sem usar uma solução alternativa, onde você pode substituir o UIAlertController da Apple não personalizável por um alerta super personalizável.

Compatível com Xcode 8, Swift 3 e Objective-C

Exemplo PMAlertController


Recursos:

  • [x] Visualização do cabeçalho
  • [x] Imagem do cabeçalho (opcional)
  • [x] Título
  • [x] Descrição da mensagem
  • [x] Personalizações: fontes, cores, dimensões e mais
  • [x] 1, 2 botões (horizontalmente) ou 3+ botões (verticalmente)
  • [x] Fechamento quando um botão é pressionado
  • [x] Suporte para campos de texto
  • [x] Implementação semelhante ao UIAlertController
  • [x] Cocoapods
  • [x] Cartago
  • [x] Animação com UIKit Dynamics
  • [x] Compatibilidade Objective-C
  • [x] Suporte para Swift 2.3 e Swift 3
Paolo Musolino
fonte
O PMAlertController permite quebra de linha quando o texto é longo nos botões de ação?
zeeple
@zeeple considera que o botão de ação é uma subclasse de UIButton. Algo assim actionButton.titleLabel.lineBreakMode = NSLineBreakByWordWrappingfunciona bem.
Paolo Musolino
3

Há um problema com a definição da cor de matiz na exibição após a apresentação; mesmo se você fizer isso no bloco de conclusão de presentViewController: animated: completed :, isso causa um efeito de oscilação na cor dos títulos dos botões. Isso é desleixado, pouco profissional e completamente inaceitável.

Outras soluções apresentadas dependem de a hierarquia de visualização permanecer estática, algo que a Apple detesta fazer. Espere que essas soluções falhem em versões futuras do iOS.

A única maneira infalível de resolver esse problema e fazê-lo em qualquer lugar é adicionando uma categoria ao UIAlertController e fazendo o swizzling do viewWillAppear.

O cabeçalho:

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

A implementação:

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

Adicione um .pch (cabeçalho pré-compilado) ao seu projeto e inclua a categoria:

#import "UIAlertController+iOS9TintFix.h"

Certifique-se de registrar seu pch no projeto corretamente, e ele incluirá os métodos de categoria em cada classe que usa o UIAlertController.

Em seguida, no método didFinishLaunchingWithOptions dos delegados do seu aplicativo, importe sua categoria e chame

[UIAlertController tintFix];

e ele se propagará automaticamente para cada instância do UIAlertController dentro do seu aplicativo, seja iniciado pelo seu código ou por qualquer outra pessoa.

Esta solução funciona para iOS 8.X e iOS 9.X e não apresenta a oscilação da abordagem pós-apresentação da mudança de tonalidade. Também é completamente agnóstico em relação à hierarquia de visualizações das subvisões do UIAlertController.

Feliz hacking!

ObiDan
fonte
Esta solução funciona, principalmente. Na rotação do dispositivo, no entanto, as tonalidades voltam a ser como eram, antes do swizzling.
Dhiraj Gupta
Dhiraj, acabei de testar isso novamente em uma configuração de projeto explicitamente para explorar suas descobertas, e não concordo. A tonalidade não volta à forma como estava na rotação.
ObiDan
Verificado funcional no xcode 6.4 e xcode 7.0. Simuladores de execução de todas as variações de 8.X e 9.0. Se solicitado, colocarei o projeto no github.
ObiDan
Bem, você poderia ir em frente e colocar um projeto, mas era isso que eu estava vendo acontecendo comigo. Também não estava funcionando no iPad. Com base na sua ideia método swizzling, no entanto, eu era capaz de fazê-lo funcionar por viewDidLayoutSubviews swizzling, no entanto.
Dhiraj Gupta
Se você colocar um projeto, eu poderia enviar uma solicitação de pull com o swizzle viewDidLayoutSubviews, que é o que acabei de usar e enviar na compilação mais recente do meu aplicativo para a App Store e você pode dar uma olhada, talvez?
Dhiraj Gupta
3

Por favor encontre isto categoria. Eu sou capaz de mudar FONT e Color de UIAlertAction e UIAlertController.

Usar:

UILabel * appearanceLabel = [UILabel appearanceWhenContainedIn:UIAlertController.class, nil];
[appearanceLabel setAppearanceFont:yourDesireFont]];  
Arpan Dixit
fonte
5
Por favor, cole o código aqui ou use um serviço que não exija o login de pessoas.
Sulthan
3

Em 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)
})
iOS
fonte
sua resposta precisa de uma atualização, self.present(alertController, animated: true)ou self.present(alert, animated: true).
Yash Bedi
@Yash Bedi, obrigado, atualizei minha resposta, verifique uma vez.
iOS
2

Solução / hack para 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");
    }];
Akhilesh Sharma
fonte
Eu tentei isso. Observe que você está revertendo a configuração de tonalidade da janela assim que o controlador de alerta é apresentado. Eu vejo a cor mudando de volta diretamente no controlador de alerta. Acredito que a reverência deve ser feita assim que qualquer ação for acionada.
Germán
Obrigado @ Germán por apontar isso .. Fiz as alterações no código. Estou lidando com a reversão na AlertAction a partir de agora .. Mas sim, eu concordo que pode ser tratada no manipulador de dimiss também
Akhilesh Sharma
1

Eu trabalho para Urban Outfitters. Temos um pod de código aberto URBNAlert, que usamos em todos os nossos aplicativos. É baseado emUIAlertController , mas é altamente personalizável.

A fonte está aqui: https://github.com/urbn/URBNAlert

Ou simplesmente instale pelo pod, colocando URBNAlertem seu Podfile

Aqui está um código de amostra:

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];
RyanG
fonte
Isso é compatível com o estilo ActionSheet?
Danpe
@Danpe não, é puramente apenas para Alertas .. Dito isso .. se for algo que você deseja, crie um problema no repo. Isso é algo para o qual já discutimos adicionar suporte
RyanG
1

Para alterar a cor de um botão como CANCELAR para vermelho, você pode usar esta propriedade de estilo chamada 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);
Kazim Ahmad
fonte
1

Para iOS 9.0 e superior, use este código no delegado do aplicativo

[[UIView appearanceWhenContainedInInstancesOfClasses:@[[UIAlertController class]]] setTintColor:[UIColor redColor]];
iOS
fonte
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")
Hiren Panchal
fonte
0

Um pouco desajeitado, mas agora funciona para mim definir as cores do fundo e do texto. Eu encontrei aqui .

UIView * firstView = alertController.view.subviews.firstObject;
    UIView * nextView = firstView.subviews.firstObject;
    nextView.backgroundColor = [UIColor blackColor];
TheGeezer
fonte
Funciona para a cor de fundo, mas nunca muda a cor da tonalidade, é com isso que estou um pouco confuso
Akhilesh Sharma
0

Eu criei um método objetivo-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];
}

Código funcionando perfeitamente no Xcode 8.3.1. Você pode personalizar de acordo com a necessidade.

Alok
fonte
0

Eu apenas uso esse tipo de demanda, aparentemente e sistema, os detalhes são um pouco diferentes, então somos ... OC percebeu o encapsulamento da janela popup de Alerta e Folha.

Freqüentemente encontrado no desenvolvimento diário, a necessidade de adicionar uma figura para alertar ou alterar a cor de um botão, como a demanda "simples", hoje traz um sistema de componentes e altamente semelhantes e pode atender totalmente a demanda de componentes de embalagens personalizadas.

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

Tim
fonte