Reputation: 1385
I've been having trouble trying to set the UIDatePicker
font and color. Everything else in my app was fairly straightforward to adjust except this. Does anybody know how to do this? I'm using Swift for iOS8.
Upvotes: 32
Views: 36450
Reputation: 399
The only way for changing the font of UIDatePickerView (until now) is swizzling:
you can change the font by an extension of UILabel! (this is not recommended but it works!)
import Foundation
import UIKit
public extension UILabel {
@objc func setFontSwizzled(font: UIFont) {
if self.shouldOverride() {
self.setFontSwizzled(font: <THE UIFont FOR ALL DATEPICKERS!>)
} else {
self.setFontSwizzled(font: font)
}
}
private func shouldOverride() -> Bool {
let classes = ["UIDatePicker", "UIDatePickerWeekMonthDayView", "UIDatePickerContentView"]
var view = self.superview
while view != nil {
let className = NSStringFromClass(type(of: view!))
if classes.contains(className) {
return true
}
view = view!.superview
}
return false
}
private static let swizzledSetFontImplementation: Void = {
let instance: UILabel = UILabel()
let aClass: AnyClass! = object_getClass(instance)
let originalMethod = class_getInstanceMethod(aClass, #selector(setter: font))
let swizzledMethod = class_getInstanceMethod(aClass, #selector(setFontSwizzled))
if let originalMethod = originalMethod, let swizzledMethod = swizzledMethod {
// switch implementation..
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}()
static func swizzleSetFont() {
_ = self.swizzledSetFontImplementation
}
}
and for changing the color you just simply call the function below:
datePicker.setValue(UIColor.whiteColor(), forKeyPath: "textColor")
if it's necessary to be re-rendered you need to call:
datePicker.datePickerMode = .CountDownTimer
datePicker.datePickerMode = .DateAndTime //or whatever your original mode was
Upvotes: 9
Reputation: 7778
In Xcode 11.5, iOS 13, mode is set automatically, by setting the date picker colors in your storyboard as follows:
background: systemBackgroundColor text: labelColor
This results in the following:
I found that I also had to set the interface style in the simulator settings:
Upvotes: 0
Reputation: 4308
This worked for me:
setting text color for all date picker subviews
for view in datePicker.subviews {
view.setValue(UIColor.white, forKeyPath: "textColor")
}
Upvotes: 1
Reputation: 1
I ran into a similar issue with the latest SwiftUI / Swift 5 on XCode 11. All of the options above did not work and the DatePicker either stayed black text or crashed.
In your SwiftUI file set init() before var body
init() {
UIDatePicker.appearance().backgroundColor = .clear
}
Then in your var body view do this
DatePicker(selection: $dob, in: ...Date(), displayedComponents: .date) {
Text("Select Date")
}.colorInvert()
That inverted the black text to be white using the iOS Dark Theme. Looks/works great. Hope this helps.
Upvotes: 0
Reputation: 1790
Swift 4
override func layoutSubviews() {
super.layoutSubviews()
datePickerView.setValue(UIColor.white, forKeyPath: "textColor")
}
Upvotes: 4
Reputation: 1344
You can use extensions to get and set textColor like bellow
extension UIDatePicker {
var textColor: UIColor? {
set {
setValue(newValue, forKeyPath: "textColor")
}
get {
return value(forKeyPath: "textColor") as? UIColor
}
}
}
And then set the color:
datePicker.textColor = .red
Upvotes: 3
Reputation: 853
you just need to set 2 lines of code in viewdidLoad
/ viewWillAppear
accoding where you using DatePicker.
dobDatePicker.setValue(UIColor.whiteColor(), forKeyPath: "textColor")
dobDatePicker.setValue(false, forKey: "highlightsToday")
See the Result like this:
Upvotes: 20
Reputation: 6697
Adding textColor and highlightsToday to user defined variables did the trick for me :
Upvotes: 4
Reputation: 2507
I believe this is the definitive solution for countdown timers.
It's an expansion of yildirimosman's answer.
//text color
datePicker.setValue(UIColor.whiteColor(), forKey: "textColor")
//picker background
datePicker.subviews[0].subviews[0].backgroundColor = UIColor.clearColor() //the picker's own background view
//dividers
datePicker.subviews[0].subviews[1].backgroundColor = UIColor.whiteColor()
datePicker.subviews[0].subviews[2].backgroundColor = UIColor.whiteColor()
//labels: "hours" and "min"
datePicker.subviews[0].subviews[3].setValue(UIColor.lightGrayColor(), forKey: "textColor")
datePicker.subviews[0].subviews[4].setValue(UIColor.lightGrayColor(), forKey: "textColor")
//refresh the tableview (to force initial row textColor to change to white)
datePicker.subviews[0].setNeedsLayout()
datePicker.subviews[0].layoutIfNeeded()
Upvotes: 6
Reputation: 132
you can use
datePicker.setValue(UIColor.whiteColor(), forKey: "textColor")
datePicker.setValue(false, forKey: "highlightsToday")
//for selector color
datePickerView.subviews[0].subviews[1].backgroundColor = UIColor.whiteColor()
datePickerView.subviews[0].subviews[2].backgroundColor = UIColor.whiteColor()
Upvotes: 6
Reputation: 53
I wanted to do this but set it for when someone has the date set prior to now, or after now. I had to reload the data, but when I did it ended up setting it to the current DateTime when using the above example.
So what I did was set a temporary value and then set it after the reload. It does make it do an animated effect, but it works. If you know a better way, let me know...
func dateChanged(sender: UIDatePicker) {
print(sender.date.description)
let tempDate = sender.date
let currentDate = NSDate()
if originalDate.isLessThanDate(currentDate) {
originalDate = sender.date
if sender.date.isGreaterThanDate(currentDate) {
sender.setValue(UIColor.blackColor(), forKeyPath: "textColor")
sender.datePickerMode = .CountDownTimer
sender.datePickerMode = .DateAndTime
sender.date = tempDate
sender.reloadInputViews()
}
}
if sender.date.isLessThanDate(currentDate) {
sender.setValue(UIColor.redColor(), forKeyPath: "textColor")
sender.datePickerMode = .CountDownTimer
sender.datePickerMode = .DateAndTime
sender.date = tempDate
sender.reloadInputViews()
}
}
Upvotes: 3
Reputation: 1001
try this:
/* set color for UIDatePicker font */
//text color of today string
self.datePicker.performSelector("setHighlightsToday:", withObject:Constants.Colors.mainHeaderColor)
//text color for hoglighted color
self.datePicker.performSelector("_setHighlightColor:", withObject:Constants.Colors.mainHeaderColor)
//other text color
self.datePicker.setValue(Constants.Colors.mainHeaderColor, forKey: "textColor")
Upvotes: 4
Reputation: 1430
Changing the date mode to something else seems to force a re-draw with the newly set text color.
datePicker.setValue(UIColor.whiteColor(), forKeyPath: "textColor")
datePicker.datePickerMode = .CountDownTimer
datePicker.datePickerMode = .DateAndTime //or whatever your original mode was
Upvotes: 35
Reputation: 2391
You can set value using forKeyPath: "textColor". The code:
datePicker.setValue(UIColor.whiteColor(), forKeyPath: "textColor")
where datePicker is your UIDatePicker object, and the first parameter is the color that you want
Upvotes: 3
Reputation: 2395
I saw the issue you were having and was having a similar issue. Using Xcode 6.3.1 I used this code in mine and worked great:
myPicker.backgroundColor = UIColor.whiteColor()
In case this helps.
Upvotes: 1
Reputation: 9686
The API does not provide a way to do this. You can make a pretty convincing replica yourself using a UIPickerView rather than using UIDatePicker. Se here
Upvotes: 3