UIAlertController niestandardowa czcionka, rozmiar, kolor

118

Używam nowego UIAlertController do wyświetlania alertów. Mam ten kod:

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

Teraz chcę zmienić tytuł i czcionkę wiadomości, kolor, rozmiar itd. Jak najlepiej to zrobić?

Edycja: powinienem wstawić cały kod. Stworzyłem kategorię dla UIView, w której mogłem wyświetlać odpowiedni alert dla wersji 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
źródło
2
DISCLAIMER:Do każdego, kto czyta poniższe odpowiedzi. Apple odrzuci Twoje aplikacje. Jeśli zazwyczaj korzystasz z prywatnych interfejsów API. A w poniższych odpowiedziach TO CO SIĘ DZIEJE ...
Yash Bedi

Odpowiedzi:

98

Nie jestem pewien, czy jest to sprzeczne z prywatnymi interfejsami API / właściwościami, ale używanie KVC działa dla mnie na 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"];

Dla przypomnienia, można również zmienić czcionkę akcji alarmowej, korzystając z tych prywatnych interfejsów API. Ponownie, może to spowodować odrzucenie aplikacji, nie próbowałem jeszcze przesłać takiego kodu.

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

Dla Swift 4.2 w XCode 10 i nowszych ostatnie 2 linie to teraz:

guard let label = (action!.value(forKey: "__representer")as? NSObject)?.value(forKey: "label") as? UILabel else { return }
        label.attributedText = attributedText
dupuis2387
źródło
6
To działa. attributedTitledla tytułu i attributedMessagewiadomości. Nie jestem pewien, czy to najlepsze rozwiązanie, ale na razie wystarczy dla mnie.
Libor Zapletal
2
jakie wszystkie dostosowania możemy dodać do przycisków UIAlertController?
Aanchal Chaurasia
1
Dzięki! Mam małe pytanie - można użyć niestandardowych czcionek i kolorów z kafelkiem atrybutu i komunikatem w UIAlertController. Jak można zrobić to samo z UIAlertAction?
p0lAris
72
Mam nadzieję, że nikt z was nie planuje udostępnić tego do sklepu z aplikacjami, ponieważ korzysta on z prywatnych interfejsów API. Poważnie, nie mam pojęcia, dlaczego te odpowiedzi są kiedykolwiek akceptowane w Stackoverflow, kiedy tak naprawdę nie są „odpowiedziami”. Są to hacki, których opublikowanie w sklepie z aplikacjami może, ale nie musi.
TheCodingArt
3
W przypadku wypuszczania aplikacji w sklepie z aplikacjami Apple zezwala na niektóre prywatne zastosowania API, ale nie powinno używać API, które może zaszkodzić lub wpłynąć na system / prywatność użytkownika. Tak więc prawdopodobnie ta odpowiedź może zostać zaakceptowana przez wiele osób tylko z tego powodu. I prawdopodobnie nie ma to wpływu na sklep z aplikacjami. Czy ktoś, kto z tego korzystał, może potwierdzić, że jego aplikacja nie została odrzucona?
Mehul Thakkar
66

Możesz zmienić kolor przycisku, stosując kolor tinty do UIAlertController.

W systemie iOS 9, jeśli kolor tinta okna został ustawiony na niestandardowy kolor, musisz zastosować kolor tinta zaraz po przedstawieniu alertu. W przeciwnym razie kolor odcień zostanie zresetowany do niestandardowego koloru odcienia okna.

// 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
źródło
20
Dla wyjaśnienia ustawienie tintColor po przedstawieniu kontrolera działa zarówno na iOS 8, jak i 9, więc nie jest konieczne ustawianie go dwukrotnie.
arlomedia
Dziękujemy za dodanie
szybkiej
3
Kiedy stuknę i przeciągnę palcem w dół, ponownie wróci do domyślnego koloru. Dowolny pomysł?
msmq
To naprawdę jedyna przyzwoita odpowiedź.
TheCodingArt
47

Możesz zmienić kolor tekstu przycisku za pomocą tego kodu:

alertC.view.tintColor = your color;

Może to ci pomoże.

ChintaN -Maddy- Ramani
źródło
@esilver, czy udało Ci się znaleźć rozwiązanie działające z iOS9?
Ash
1
Ja nie. Utworzyłem raport o błędzie w Apple, # 22391695.
esilver
1
Więcej informacji na ten temat. Wygląda na to, że kiedy przewijasz długie pozycje listy, ten, którego dotykasz, aby przewijać, staje się niebieski ...
Bejil
3
Żadna z tych prac nie działa na UIAlertController w iOS9 i 9.1 .. Nie wiem, co robią ludzie z Apple ... Trzeba ręcznie zmieniać odcień okna za każdym razem, gdy wywoływany jest kontroler alertów i zmieniać go z powrotem w module obsługi.
Akhilesh Sharma
Działa z iOS 9.3, chyba że wykonasz poprawki poza domem: wraca do systemu niebieskiego
Rémi Belzanti
35

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

}

Wynik

UIAlertController niestandardowa czcionka, rozmiar i kolor

Ashok R
źródło
Przepraszam brachu, to się zaczyna. Jeśli będzie to wymagane w funkcji, poinformuję Cię ...
iOS
24

Szybkie tłumaczenie odpowiedzi @ dupuis2387. Opracowano składnię, aby ustawić UIAlertControllerkolor i czcionkę tytułu za pomocą KVC za pomocą attributedTitleklawisza.

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)

wprowadź opis obrazu tutaj

Robert Chen
źródło
3
A co z przyciskiem „OK”? Czy możemy to dostosować?
Hassan Taleb
@HassanTaleb Nie znalazłem świetnego sposobu na dostosowanie przycisku. Możesz ustawić tintColorna viewlub przez appearanceWhenContainedIn, ale odcień znika, gdy tylko go dotkniesz. Wciąż jednak szukam odpowiedzi.
Robert Chen,
@AbdulMomen عبدالمؤمن Jaki komunikat o błędzie widzisz? Fragment kodu zakłada, że ​​FontAwesome jest już skonfigurowany.
Robert Chen,
1
@RobertChen aby rozwiązać problem, po prostu umieść odcień po:, self.presentViewController(alertController, animated: true, completion: nil)czy możemy zmienić czcionkę przycisku „OK”?
Hassan Taleb
4
Czy to nie jest uważane za prywatny interfejs API?
Jinghan Wang
13

Użyj UIAppearanceprotokołu. Przykład ustawienia czcionki - utwórz kategorię do rozszerzenia 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

I jego zastosowanie:

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

Przetestowane i działające ze stylem UIAlertControllerStyleActionSheet, ale myślę, że też będzie działać UIAlertControllerStyleAlert.

PS Lepiej sprawdź dostępność klas zamiast wersji iOS:

if ([UIAlertController class]) {
    // UIAlertController code (iOS 8)
} else {
    // UIAlertView code (pre iOS 8)
}
Ivan
źródło
Działa, ale w ten sposób nie mogę mieć innego rozmiaru wiadomości i tytułu.
Libor Zapletal
To działa, ale po kliknięciu akcji czcionka powraca do pierwotnego rozmiaru? Czy to się dzieje dla Ciebie?
Larry
Mam ten sam problem @ Larry i nie znalazłem sposobu, żeby sobie z nim poradzić.
alasker
12

Użyj UIAppearanceprotokołu. Zrób więcej hacków, appearanceFontaby zmienić czcionkę UIAlertAction.

Utwórz kategorię dla 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

Stosowanie:

Dodaj

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

w AppDelegate.m, aby pracować dla wszystkich UIAlertController.

user3480295
źródło
Tytuł w iOS 8.3 ma 13 punktów i jest pogrubiony, więc zmieniłem warunek naif (self.font.pointSize == 13 && isBold) {
Andrew Raphael
Wspomniałeś o zmianie czcionki dla UIAlertAction. Ale o ile wiem, UIAlertActionnie używa UILabel. Używa NSString. github.com/nst/iOS-Runtime-Headers/blob/… Nie wiem, jak można dostosować czcionkę do pliku NSString.
peacetype
UIAlertAction w ogóle nie jest klasą widoku. Jest to abstrakcyjna klasa opisująca akcję. Sam widok jest następnie generowany wewnątrz UIAlertController. Dlatego ustawiasz wygląd zawarty w UIAlertController.
mangerlahn
12

Swift 5 i 5.1 . Utwórz osobny plik i umieść tam kod dostosowywania UIAlertController

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

Teraz w każdej akcji Pokaż alert

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

Wynik

wprowadź opis obrazu tutaj

Gurjinder Singh
źródło
1
czy mamy tu dostęp do jakichkolwiek prywatnych interfejsów API.? Czy wydałeś jakąkolwiek aplikację z tymi wieloma niestandardowymi właściwościami alertów?
Yash Bedi
@YashBedi korzysta z prywatnych interfejsów API i Apple może odrzucić Twoją aplikację z powodu używania „niepublicznego interfejsu API”. Nie, nie wydałem żadnej aplikacji.
Gurjinder Singh
Jest to wspomniane w witrynie programistów Apple -> Ważne Klasa UIAlertController jest przeznaczona do użycia w takiej postaci, w jakiej jest i nie obsługuje podklas. Hierarchia widoków dla tej klasy jest prywatna i nie można jej modyfikować.
Gurjinder Singh
Rozumiem Szefie Dziękuję.
Yash Bedi
@Darkglow Proszę wspomnieć o błędzie. Jestem w stanie pomyślnie zbudować ten sam kod za pomocą Swift 5.1
Gurjinder Singh
10

Używam tego.

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

Dodaj jedną linię (AppDelegate) i działa dla wszystkich UIAlertController.

Lucas Torquato
źródło
3
Ponieważ jest to obecnie przestarzałe, użyj [[UIView lookWhenContainedInInstancesOfClasses: @ [[UIAlertController class]]] setTintColor: newColor]; zamiast tego
Peter Johnson,
8

Szybki 4

Przykład niestandardowej czcionki w tytule. To samo dotyczy innych składników, takich jak komunikat lub akcje.

    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)
Anthony R.
źródło
5

Oto rozszerzenie dla Swift 4.1 i 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
źródło
4

Właśnie ukończyłem wymianę UIAlertController. To jest jedyna rozsądna droga, myślę:


Stary

Oto moja metoda w języku Swift, która zbiera wiele informacji z odpowiedzi tutaj

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

W niektórych sytuacjach działa to doskonale, w innych jest to kompletna porażka (kolory odcieni nie pokazują się zgodnie z oczekiwaniami).

Dan Rosenstark
źródło
4

Możesz użyć zewnętrznej biblioteki, takiej jak PMAlertController, bez stosowania obejścia, w której możesz zastąpić niemożliwy do dostosowania kontroler UIAlertController firmy Apple z super konfigurowalnym alertem.

Kompatybilny z Xcode 8, Swift 3 i Objective-C

Przykład PMAlertController


Cechy:

  • [x] Widok nagłówka
  • [x] Obraz nagłówka (opcjonalny)
  • [x] Tytuł
  • [x] Opis komunikatu
  • [x] Dostosowania: czcionki, kolory, wymiary i nie tylko
  • [x] 1, 2 przyciski (poziomo) lub 3+ przyciski (pionowo)
  • [x] Zamknięcie po naciśnięciu przycisku
  • [x] Obsługa pól tekstowych
  • [x] Podobna implementacja do UIAlertController
  • [x] Cocoapods
  • [x] Kartagina
  • [x] Animacja z UIKit Dynamics
  • [x] Zgodność Objective-C
  • Obsługa [x] Swift 2.3 i Swift 3
Paolo Musolino
źródło
Czy PMAlertController umożliwia zawijanie słów, gdy tekst w przyciskach akcji jest długi?
zeeple
@zeeple uważa, że ​​przycisk akcji jest podklasą UIButton. Coś takiego actionButton.titleLabel.lineBreakMode = NSLineBreakByWordWrappingdziała dobrze.
Paolo Musolino
3

Występuje problem z ustawieniem odcienia na podglądzie po prezentacji; nawet jeśli zrobisz to w bloku uzupełniania presentViewController: animated: Complete:, powoduje to efekt migotania koloru tytułów przycisków. To jest niechlujne, nieprofesjonalne i całkowicie niedopuszczalne.

Inne przedstawione rozwiązania zależą od statycznej hierarchii widoków, czego Apple nie lubi. Spodziewaj się, że te rozwiązania zawiodą w przyszłych wersjach systemu iOS.

Jedynym niezawodnym sposobem rozwiązania tego problemu i zrobienia tego wszędzie, jest dodanie kategorii do UIAlertController i przełączenie widokuWillAppear.

Nagłówek:

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

Implementacja:

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

Dodaj .pch (prekompilowany nagłówek) do projektu i dołącz kategorię:

#import "UIAlertController+iOS9TintFix.h"

Upewnij się, że poprawnie zarejestrowałeś swój PC w projekcie i będzie zawierał metody kategorii w każdej klasie, która używa UIAlertController.

Następnie w metodzie didFinishLaunchingWithOptions delegatów aplikacji zaimportuj kategorię i wywołaj

[UIAlertController tintFix];

i automatycznie rozprzestrzeni się na każdą instancję UIAlertController w Twojej aplikacji, niezależnie od tego, czy została uruchomiona przez Twój kod, czy przez kogokolwiek innego.

To rozwiązanie działa zarówno na iOS 8.X, jak i iOS 9.X i brakuje mu migotania po zmianie odcienia podejścia po prezentacji. Jest również całkowicie agnostyczny w odniesieniu do hierarchii widoków widoków podrzędnych kontrolera UIAlertController.

Miłego hakowania!

ObiDan
źródło
To rozwiązanie w większości działa. Jednak po obróceniu urządzenia odcienie wracają do stanu sprzed migotania.
Dhiraj Gupta
Dhiraj, właśnie przetestowałem to ponownie w konfiguracji projektu, wyraźnie w celu zbadania twoich ustaleń, i nie zgadzam się z tym. Odcień nie wraca do stanu, w jakim był przy obracaniu.
ObiDan
Sprawdzono, czy działa na xcode 6.4 i xcode 7.0. Uruchamianie symulatorów wszystkich wersji 8.X i 9.0. Na życzenie umieszczę projekt na githubie.
ObiDan
Cóż, możesz iść dalej i rozpocząć projekt, ale właśnie to się ze mną dzieje. Nie działał też na iPadzie. W oparciu o metodę swizzling pomysł, ale ja był w stanie zrobić to praca przez swizzling viewDidLayoutSubviews, choć.
Dhiraj Gupta
Jeśli opublikujesz projekt, mógłbym przesłać żądanie ściągnięcia z zawijasem viewDidLayoutSubviews, którego właśnie użyłem i przesłałem w najnowszej wersji mojej aplikacji do App Store i może możesz rzucić okiem?
Dhiraj Gupta
3

Proszę, znajdź to kategorię. Jestem w stanie zmienić FONT i kolor UIAlertAction i UIAlertController.

Posługiwać się:

UILabel * appearanceLabel = [UILabel appearanceWhenContainedIn:UIAlertController.class, nil];
[appearanceLabel setAppearanceFont:yourDesireFont]];  
Arpan Dixit
źródło
5
Wklej kod tutaj lub skorzystaj z usługi, która nie wymaga logowania.
Sulthan
3

W Swift 4.1 i 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
źródło
Twoja odpowiedź wymaga aktualizacji self.present(alertController, animated: true)lub self.present(alert, animated: true).
Yash Bedi
@Yash Bedi, dziękuję zaktualizowałem moją odpowiedź, sprawdź ją raz.
iOS
2

Rozwiązanie / Hack dla 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
źródło
Próbowałem tego. Zwróć uwagę, że po wyświetleniu kontrolera alertów przywracasz ustawienie odcienia okna. Widzę, jak kolor zmienia się z powrotem bezpośrednio na kontrolerze alertów. Uważam, że przywrócenie należy wykonać po dotknięciu jakiejkolwiek czynności.
Germán
Dzięki @ Germán za wskazanie tego… Wprowadziłem zmiany w kodzie. Od teraz zajmuję się przywracaniem w AlertAction .. Ale tak, zgadzam się, że można to również załatwić w programie obsługi dimiss
Akhilesh Sharma
1

Pracuję dla Urban Outfitters. Mamy moduł open source URBNAlert, którego używaliśmy we wszystkich naszych aplikacjach. Jest oparty naUIAlertController , ale jest wysoce konfigurowalny.

Źródło jest tutaj: https://github.com/urbn/URBNAlert

Lub po prostu zainstaluj przez kapsułę, umieszczając URBNAlertw swoim pliku Podfile

Oto przykładowy kod:

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
źródło
Czy to obsługuje styl ActionSheet?
Danpe
@Danpe nie robi, to jest wyłącznie dla alertów .. Biorąc to pod uwagę ... jeśli jest to coś, czego chcesz, stwórz problem w repozytorium. To jest coś, o czym rozmawialiśmy wcześniej, dodając wsparcie
RyanG
1

Aby zmienić kolor jednego przycisku, takiego jak CANCEL, na czerwony, możesz użyć tej właściwości stylu o nazwie 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
źródło
1

W przypadku systemu iOS 9.0 i nowszych użyj tego kodu w delegacie aplikacji

[[UIView appearanceWhenContainedInInstancesOfClasses:@[[UIAlertController class]]] setTintColor:[UIColor redColor]];
iOS
źródło
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
źródło
0

Trochę niezgrabne, ale teraz działa to dla mnie, aby ustawić kolory tła i tekstu. Znalazłem to tutaj .

UIView * firstView = alertController.view.subviews.firstObject;
    UIView * nextView = firstView.subviews.firstObject;
    nextView.backgroundColor = [UIColor blackColor];
TheGeezer
źródło
Działa na kolor tła, ale nigdy nie zmienia koloru odcienia, to jest to, co mnie trochę zdezorientowało
Akhilesh Sharma
0

Stworzyłem jedną metodę celu-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];
}

Kod działa doskonale w Xcode 8.3.1. Możesz dostosować zgodnie z wymaganiami.

Alok
źródło
0

Po prostu używam tego rodzaju żądania, pozornie i systemu, szczegóły są nieco inne, więc ... OC zrealizowało hermetyzację okna wyskakującego Alert i Arkusz.

Często spotykana w codziennych pracach rozwojowych potrzeba dodania cyfry do Alertów lub zmiany koloru przycisku, np. „Proste” żądanie, obecnie przynosi bardzo podobne elementy systemu i może w pełni zaspokoić zapotrzebowanie na niestandardowe elementy opakowania.

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

Tim
źródło