【问题标题】:UIAlertController custom font, size, colorUIAlertController 自定义字体、大小、颜色
【发布时间】:2014-12-15 03:26:48
【问题描述】:

我正在使用新的 UIAlertController 来显示警报。我有这个代码:

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

现在我想更改标题和消息字体、颜色、大小等。最好的方法是什么?

编辑: 我应该插入整个代码。我为 UIView 创建了可以为 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];
    }
}

【问题讨论】:

  • DISCLAIMER: 致所有阅读以下答案的人。 Apple 将拒绝您的应用程序。如果您倾向于使用任何私有 API。在下面的答案中,这就是正在发生的事情..

标签: ios objective-c ios8 uialertview uialertcontroller


【解决方案1】:

不确定这是否违反私有 API/属性,但在 ios8 上使用 KVC 对我有用

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

作为记录,使用这些私有 API 也可以更改警报操作的字体。同样,它可能会让你的应用被拒绝,我还没有尝试提交这样的代码。

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

对于 XCode 10 及以上版本中的 Swift 4.2,最后两行现在是:

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

【讨论】:

  • 它工作正常。 attributedTitle 用于标题,attributedMessage 用于消息。不确定这是否是最好的解决方案,但现在对我来说已经足够了。
  • 我们可以在 UIAlertController 按钮上添加哪些自定义项??
  • 谢谢!我有一个小问题——可以使用UIAlertController 中的属性磁贴和消息自定义字体和颜色。 UIAlertAction 怎么能做到这一点?
  • 我希望你们中没有人打算将它发布到应用商店,因为它使用私有 API。说真的,我不知道为什么这些答案在它们不是真正的“答案”时会在 Stackoverflow 上被接受。这些是您在应用商店中发布时可能会或可能不会逃脱的黑客。
  • 对于在应用商店发布应用的情况,苹果允许使用一些私有api,但不应使用可能损害或影响用户系统/隐私的api。所以,可能这个答案可能会被很多人接受,仅因为这一点。并且可能它可能不会影响应用商店。使用过这个的人可以确认他们的应用没有被拒绝吗?
【解决方案2】:

您可以通过将色调颜色应用于 UIAlertController 来更改按钮颜色。

在 iOS 9 上,如果窗口色调颜色设置为自定义颜色,您必须在显示警报后立即应用色调颜色。否则,色调颜色将重置为您的自定义窗口色调颜色。

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

【讨论】:

  • 澄清一下,在呈现控制器后设置 tintColor 适用于 iOS 8 和 9,因此无需设置两次。
  • 感谢您在 iOS 9 中添加 Swift 答案和解决此问题的方法。
  • 当我点击并向下拖动手指时,它会再次变为默认颜色。有什么想法吗?
  • 这确实是这里唯一不错的答案。
【解决方案3】:

您可以使用以下代码更改按钮文本的颜色:

alertC.view.tintColor = your color;

也许这会对你有所帮助。

【讨论】:

  • @esilver 你找到适用于 iOS9 的解决方案了吗?
  • 我没有。我与 Apple 创建了一个错误报告,#22391695。
  • 更多信息。似乎当您滚动长列表项时,您触摸滚动的项目变为蓝色......
  • 在 iOS9 和 9.1 中的 UIAlertController 上这些都不起作用。不知道苹果人在做什么...需要在每次调用警报控制器时手动更改窗口色调并将其更改回处理程序。
  • 它适用于 iOS 9.3,除非你在外面修改:回到系统蓝色
【解决方案4】:

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

}

输出

【讨论】:

  • 对不起兄弟,这是启动。如果功能需要,我会通知您...
【解决方案5】:

@dupuis2387 答案的 Swift 翻译。通过 KVC 使用 attributedTitle 键,制定了设置 UIAlertController 标题颜色和字体的语法。

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)

【讨论】:

  • “确定”按钮怎么样?我们可以定制它吗?
  • @HassanTaleb 我还没有找到自定义按钮的好方法。您可以在viewappearanceWhenContainedIn 上设置tintColor,但一旦触摸它,颜色就会消失。不过仍在寻找答案。
  • @AbdulMomenعبدالمؤمن 您看到什么错误消息?代码 sn-p 假设 FontAwesome 已经设置好了。
  • @RobertChen 来解决这个问题,只需将 tint 放在 :self.presentViewController(alertController, animated: true, completion: nil) 之后,我们可以更改按钮“OK”的字体吗?
  • 这不是私有的api吗?
【解决方案6】:

Swift 5 和 5.1。创建一个单独的文件并将 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
  }
}

现在在任何动作上显示警报

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

结果

【讨论】:

  • 我们在这里访问任何私有 Api 吗?您是否发布了具有这么多自定义警报属性的应用程序?
  • @YashBedi 它正在使用私有 API,Apple 可能会拒绝您的应用使用“非公共 API”。不,我还没有发布任何应用程序。
  • Apple 开发者网站上提到了这一点 -> 重要 UIAlertController 类旨在按原样使用,不支持子类化。此类的视图层次结构是私有的,不得修改。
  • @Darkglow 请提及错误。我能够使用 swift 5.1 成功构建相同的代码
【解决方案7】:

使用UIAppearance 协议。设置字体示例 - 创建类别以扩展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

及其用法:

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

经过测试并使用样式 UIAlertControllerStyleActionSheet,但我想它也适用于 UIAlertControllerStyleAlert

附:更好地检查课程可用性而不是 iOS 版本:

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

【讨论】:

  • 它正在工作,但这样我就不能为消息和标题设置不同的大小。
  • 这有效,但是当点击一个动作时,字体恢复到原来的大小?你会遇到这种情况吗?
  • 我有同样的问题@Larry,但我还没有找到解决方法.. 你呢?
【解决方案8】:

使用UIAppearance 协议。使用appearanceFont 进行更多修改以更改UIAlertAction 的字体。

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

用法:

添加

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

AppDelegate.m 中使其适用于所有UIAlertController

【讨论】:

  • iOS 8.3 中的标题是 13pt 和粗体,所以我将条件更改为 if (self.font.pointSize == 13 &amp;&amp; isBold) {
  • 您提到更改UIAlertAction 的字体。但据我所知,UIAlertAction 不使用UILabel。它使用NSStringgithub.com/nst/iOS-Runtime-Headers/blob/… 我不知道你如何为NSString 自定义字体。
  • UIAlertAction 根本不是一个视图类。它是一个描述动作的抽象类。然后在 UIAlertController 中生成视图本身。因此,您可以设置 UIAlertController 中包含的外观。
【解决方案9】:

我正在使用它。

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

添加一行(AppDelegate)并适用于所有 UIAlertController。

【讨论】:

  • 由于现在已弃用,请使用 [[UIView appearanceWhenContainedInInstancesOfClasses:@[[UIAlertController class]]] setTintColor:newColor];而是
【解决方案10】:

斯威夫特 4

标题上的自定义字体示例。 其他组件(例如消息或操作)也是如此。

    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)

【讨论】:

    【解决方案11】:

    您可以使用PMAlertController 等外部库而无需使用变通方法,您可以使用超级可定制的警报替换 Apple 的不可定制的 UIAlertController。

    兼容 Xcode 8、Swift 3 和 Objective-C


    特点:

    • [x] 标题视图
    • [x] 标题图片(可选)
    • [x] 标题
    • [x] 描述消息
    • [x] 自定义:字体、颜色、尺寸等
    • [x] 1、2 个按钮(水平)或 3+ 个按钮(垂直)
    • [x] 按下按钮时关闭
    • [x] 文本字段支持
    • [x] 与 UIAlertController 类似的实现
    • [x] Cocoapods
    • [x] 迦太基
    • [x] UIKit Dynamics 动画
    • [x] Objective-C 兼容性
    • [x] Swift 2.3 和 Swift 3 支持

    【讨论】:

    • 当操作按钮中的文本很长时,PMAlertController 是否允许自动换行?
    • @zeeple 认为操作按钮是 UIButton 的子类。像actionButton.titleLabel.lineBreakMode = NSLineBreakByWordWrapping 这样的东西效果很好。
    【解决方案12】:

    这是 Swift 4.1 和 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")
    
    }}
    

    【讨论】:

      【解决方案13】:

      在 Swift 4.1 和 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)
      })
      

      【讨论】:

      • 您的答案需要更新,self.present(alertController, animated: true)self.present(alert, animated: true)
      【解决方案14】:

      我刚刚完成了UIAlertController 的替换。 This 是唯一明智的选择,我认为:


      这是我在 Swift 中的方法,它融合了这里的答案中的大量信息

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

      这在某些情况下非常有效,而在其他情况下则完全失败(色调未按预期显示)。

      【讨论】:

        【解决方案15】:

        呈现后在视图上设置色调颜色有问题;即使您在 presentViewController:animated:completion: 的完成块中执行此操作,它也会对按钮标题的颜色产生闪烁效果。这是草率、不专业且完全不能接受的。

        提出的其他解决方案依赖于保持静态的视图层次结构,这是 Apple 不愿意做的事情。预计这些解决方案在未来的 iOS 版本中会失败。

        解决这个问题并在任何地方都可以解决的一个可靠方法是向 UIAlertController 添加一个类别并调整 viewWillAppear。

        标题:

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

        实现:

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

        在您的项目中添加 .pch(预编译头文件)并包含类别:

        #import "UIAlertController+iOS9TintFix.h"
        

        确保您在项目中正确注册了您的 pch,它将在每个使用 UIAlertController 的类中包含类别方法。

        然后,在您的应用程序中委托 didFinishLaunchingWithOptions 方法,导入您的类别并调用

        [UIAlertController tintFix];
        

        它会自动传播到您应用中的每个 UIAlertController 实例,无论是由您的代码还是其他任何人的代码启动。

        此解决方案适用于 iOS 8.X 和 iOS 9.X,并且没有显示后色调更改方法的闪烁。对于 UIAlertController 的子视图的视图层次结构,它也是完全不可知的。

        黑客愉快!

        【讨论】:

        • 这个解决方案大部分都有效。然而,在设备旋转时,色调会恢复到调配之前的状态。
        • Dhiraj,我刚刚在项目设置中再次对此进行了测试,以明确探索您的发现,但我不同意。色调不会恢复到旋转时的状态。
        • 在 xcode 6.4 和 xcode 7.0 上验证功能。运行 8.X 和 9.0 的所有变体的模拟器。如果有要求,我会把项目放到 github 上。
        • 好吧,你可以继续建立一个项目,但这就是我所看到的发生在我身上的事情。它也无法在 iPad 上运行。但是,根据您的方法 swizzling 想法,我 能够通过 swizzling viewDidLayoutSubviews 使其工作。
        • 如果你提出一个项目,那么我可以使用 viewDidLayoutSubviews swizzle 提交一个拉取请求,这是我刚刚在我的应用程序的最新版本中使用并提交到 App Store 和你可以看看吗?
        【解决方案16】:

        请查找this 类别。我可以更改 UIAlertAction 和 UIAlertController 的字体和颜色。

        用途:

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

        【讨论】:

        • 请在此处粘贴代码或使用不需要人登录的服务。
        【解决方案17】:

        iOS9 解决方案/Hack

            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");
            }];
        

        【讨论】:

        • 我试过这个。请注意,一旦出现警报控制器,您将恢复窗口色调设置。我在警报控制器上看到颜色切换回来。我相信一旦点击任何操作,就必须进行还原。
        • 感谢@Germán 指出这一点。对代码进行了更改。到目前为止,我正在处理 AlertAction 中的还原。但是是的,我同意也可以在 dimiss 处理程序中处理
        【解决方案18】:

        对于 iOS 9.0 及更高版本,在应用委托中使用此代码

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

        【讨论】:

          【解决方案19】:

          我在 Urban Outfitters 工作。我们有一个开源 pod,URBNAlert,我们在所有应用程序中都使用了它。它基于UIAlertController,但高度可定制。

          来源在这里:https://github.com/urbn/URBNAlert

          或者通过在您的 Podfile 中放置 URBNAlert 来简单地通过 pod 安装

          这里有一些示例代码:

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

          【讨论】:

          • 这是否支持 ActionSheet 样式?
          • @Danpe 它没有,它纯粹是为了警报.. 话虽如此.. 如果你想要的东西在回购中产生问题。这是我们之前讨论过的添加支持
          【解决方案20】:

          要将一个按钮(如 CANCEL)的颜色更改为红色,您可以使用这个名为 UIAlertActionStyle.破坏性的样式属性:

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

          【讨论】:

            【解决方案21】:

            斯威夫特 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")
            

            【讨论】:

              【解决方案22】:

              有点笨拙,但这对我来说现在可以设置背景和文本颜色。我找到了here

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

              【讨论】:

              • 它确实适用于背景颜色,但它永远不会改变色调颜色这是我有点困惑的地方
              【解决方案23】:

              我创建了一个方法objective-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];
              }
              

              代码在 Xcode 8.3.1 上完美运行。您可以根据需要定制。

              【讨论】:

                【解决方案24】:

                我就是用这种需求,貌似和系统,细节上略有不同,所以我们是……OC实现了Alert和Sheet弹窗封装。

                在日常开发中经常遇到需要在Alert中添加图形或者更改按钮颜色等“简单”的需求,今天带来了一个和系统组件高度相似,完全可以满足定制化封装组件的需求。

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

                【讨论】:

                  【解决方案25】:

                  您可以在没有任何私有 API 的情况下使用以下语法。

                  alert.view.tintColor = alert.view.tintColor = UIColor.green
                  alert.setTitle(font: UIFont.boldSystemFont(ofSize: 26), color: UIColor.darkGray)
                  alert.setMessage(font: UIFont.systemFont(ofSize: 26), color: UIColor.darkGray)
                  

                  【讨论】:

                    猜你喜欢
                    • 2022-07-25
                    • 1970-01-01
                    • 1970-01-01
                    • 2020-06-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多