Reputation: 173
I found the following code in How to change the background color of the UIAlertController? to change the background color of a UIAlertView
:
let subview = dialog.view.subviews.first! as UIView
let alertContentView = subview.subviews.first! as UIView
subview.subviews.top!
alertContentView.backgroundColor = UIColor.whiteColor()
However, it changes the background color of the entire view. How can I change only the background color of the title?
Upvotes: 2
Views: 1528
Reputation: 8391
Sample project -> Contains latest code
Step one:
Find a subview that has the right frame!
This little function will return the frame and address of all nested subviews.
We are looking for a subview that has a height that is smaller than that of the UIAlertController
and has an Origin
of 0,0
.
Height of my alertController was 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)
}
}
This prints stuff like this:
(0.0, 0.0, 270.0, 128.0) depth: [0, 0]
//frame - firstsubview - firstsubview
This might be a good candidate:
(0.0, 0.0, 270.0, 84.0) depth: [0, 1, 0, 0]
//frame - firstsubview - secondsubiew - firstsubview - firstsubview
This translates to this:
print(alertController.view.subviews[0].subviews[1].subviews[0].subviews[0].frame)
// prints (0.0, 0.0, 270.0, 84.0) -> Bingo!
Step two:
Color that subview!
alertController.view.subviews[0].subviews[1].subviews[0].subviews[0].backgroundColor = UIColor.redColor()
If you set the colour before presenting the alertController it will crash. Setting it in the 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()
}
Step three:
Make it safe! If they ever change anything to the stack this will prevent your app from crashing. Your view might not be coloured but a crash is worse.
Extend UIView to be able to fetch subviews with one of the addresses we printed earlier. Use guard
or if let
to prevent accessing non-existent subviews.
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
}
}
Step four:
Since it is not allowed to subclass UIAlertController
we might try to extend it. This won't give you access to viewDidAppear
so you can't display the UIAlertController
animated.
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 {
}
This gives you both the method to find any subviews you might want to alter and a way to add a custom function for it to that class. Without subclassing.
Call titleBackgroundColor
in the completionHandler of presentViewController
to set the color.
Upvotes: 0
Reputation: 3283
try with following its works for me.
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)
Upvotes: 1
Reputation: 38152
Try this out:
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")
Upvotes: 1