在 UIAlertController 中更改标题的背景颜色(仅)

Change background color of title (only) in UIAlertController

我在How to change the background color of the UIAlertController?中找到了下面的代码来改变UIAlertView的背景颜色:

let subview = dialog.view.subviews.first! as UIView
let alertContentView = subview.subviews.first! as UIView
subview.subviews.top!
alertContentView.backgroundColor = UIColor.whiteColor()

但是,它改变了整个视图的背景颜色。如何只更改标题的背景颜色?

试试这个:

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

let attributedString = NSAttributedString(string: "myTitle", attributes: [
    NSFontAttributeName : UIFont.systemFontOfSize(15),
    NSForegroundColorAttributeName : UIColor.redColor()
    ])

alertController.setValue(attributedString, forKey: "attributedTitle")

Sample project -> 包含最新代码

第一步:

找到具有正确框架的子视图!

这个小函数将return所有嵌套子视图的框架和地址。

我们正在寻找高度小于 UIAlertControllerOrigin0,0 的子视图。 我的 alertController 的高度是 128

func subViewStack(view:UIView, levels: [Int]) {

    var currentLevels = levels
    currentLevels.append(0)

    for i in 0..<view.subviews.count {

        currentLevels[currentLevels.count - 1] = i

        let subView = view.subviews[i]
        print(subView.frame, "depth:", currentLevels)
        subViewStack(subView, levels: currentLevels)

    }

}

这会打印如下内容:

(0.0, 0.0, 270.0, 128.0) depth: [0, 0]

//frame - firstsubview - firstsubview

这可能是一个不错的候选人:

(0.0, 0.0, 270.0, 84.0) depth: [0, 1, 0, 0]
//frame - firstsubview - secondsubiew - firstsubview - firstsubview

这转化为:

print(alertController.view.subviews[0].subviews[1].subviews[0].subviews[0].frame)
// prints (0.0, 0.0, 270.0, 84.0) -> Bingo!

第二步:

为该子视图着色!

alertController.view.subviews[0].subviews[1].subviews[0].subviews[0].backgroundColor = UIColor.redColor()

如果您在呈现 alertController 之前设置颜色,它将崩溃。 在 completionHandler works 中设置它。

presentViewController(alertController, animated: true) { () -> Void in

    self.subViewStack(alertController.view, levels: [])
    print(alertController.view.subviews[0].subviews[1].subviews[0].subviews[0].frame)
    alertController.view.subviews[0].subviews[1].subviews[0].subviews[0].backgroundColor = UIColor.redColor()

}

第三步

保证安全! 如果他们对堆栈进行了任何更改,这将防止您的应用程序崩溃。您的视图可能没有颜色,但崩溃会更糟。

扩展 UIView 以便能够使用我们之前打印的地址之一获取子视图。使用 guardif let 来防止访问不存在的子视图。

extension UIView {

    // use the printed addresses to access the views. This is safe even if the UIView changes in an update.
    func getSubView(withAddress address:[Int]) -> UIView? {

        var currentView : UIView = self

        for index in address {

            guard currentView.subviews.count > index else {
                return nil
            }
            currentView = currentView.subviews[index]

        }
        return currentView
    }
}

第四步:

因为不允许子class UIAlertController 我们可能会尝试扩展它。这不会让您访问 viewDidAppear,因此您无法显示 UIAlertController 动画。

protocol CustomAlert {

    var view : UIView! { get }

}

extension CustomAlert {

    func titleBackgroundColor(color:UIColor) {

        if view == nil {
            return
        }

        if let titleBackground = view.getSubView(withAddress: [0, 1, 0, 0]) {
            titleBackground.backgroundColor = color
        }
    }
}

extension UIAlertController : CustomAlert {

}

这为您提供了一种方法来查找您可能想要更改的任何子视图,以及一种为其添加自定义函数的方法 class。没有 subclassing。

presentViewController的completionHandler中调用titleBackgroundColor设置颜色

试着为我跟随它的作品。

 let confirmAlert = UIAlertController(title: "Application Name", message: "This is demo message.", preferredStyle: .Alert)

        let attributedString = NSAttributedString(string: "Application Name", attributes: [
            NSFontAttributeName : UIFont.systemFontOfSize(13),
            NSForegroundColorAttributeName : UIColor.greenColor()
            ])
        let defaultAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
        confirmAlert.addAction(defaultAction)

        confirmAlert.setValue(attributedString, forKey: "attributedTitle")
        UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(confirmAlert, animated: true, completion: nil)