46

All I want to do is change the font color of the UIDatePicker. I've researched other questions but they're all involving changing other properties and customizing the entire look. All I want to do is just change the font color from black to white. I find it hard to believe that I can't do such a seemingly simple task. And why wouldn't the tint color affect it? Does it even do anything?

Milo
  • 5,041
  • 7
  • 33
  • 59
  • 1
    possible duplicate of [can I change the font color of the datePicker in iOS7?](http://stackoverflow.com/questions/18807940/can-i-change-the-font-color-of-the-datepicker-in-ios7) – HalR Jan 02 '14 at 02:13
  • In question above I found my solution. – MarMass Nov 16 '14 at 17:49

17 Answers17

90

All I need (on iOS 8.x and 9.0) is this one line to change the font color:

        [my_date_picker setValue:[UIColor whiteColor] forKey:@"textColor"];

No subclassing or invoking of private APIs...


Note: today's current date will still be highlighted (in newer iOS versions). You can get around this by using the following code:

if ([my_date_picker respondsToSelector:sel_registerName("setHighlightsToday:")]) {

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"

        [my_date_picker performSelector:@selector(setHighlightsToday:) withObject:[NSNumber numberWithBool:NO]];

#pragma clang diagnostic pop

}
Albert Renshaw
  • 17,282
  • 18
  • 107
  • 195
waffles
  • 1,386
  • 12
  • 18
  • 8
    I tried, but the parts of today's date are in the wrong color, the 10 and the October are black, I don't mind the year being in the wrong color but the other 2 feels weird – vshade Oct 12 '15 at 01:11
  • 1
    @vshade, do you have a code snippet posted somewhere? happy to take a look...things still are working for me... – waffles Oct 13 '15 at 06:06
  • same thing here with "Today", at least. – Dima Deplov Oct 16 '15 at 02:22
  • 3
    This changes all text to white EXCEPT the current date (August 2 2015, for example would all be black). – rizzes Nov 19 '15 at 21:18
  • 4
    For current date `[my_date_picker performSelector:@selector(setHighlightsToday:) withObject:NO];` – Nike Kov Aug 11 '16 at 10:45
  • Is it possible to set the font as well? – Travis Griggs Dec 29 '16 at 18:42
  • @NikKov That can throw a warning in the newest version and can possibly break in future versions so I'm editing code into the answer to reflect how to handle both of the cases I just mentioned when using your method. Thanks! – Albert Renshaw May 14 '17 at 04:20
  • Code Works perfect. Thanks for help – Raj May 04 '20 at 05:44
  • I had to use this: [_datePickerOutlet setValue:UIColor.blackColor forKey:@"textColor"]; #ObjectiveC – uplearned.com May 22 '20 at 22:05
  • 1
    Figured out the default style changed, to get the wheel style back picker.preferredDatePickerStyle = .wheels is needed, then this solution continues to work – keegan3d Jul 02 '20 at 17:12
  • 1
    setHighlightsToday is no longer available on iOS 14 – Declan McKenna Oct 02 '20 at 12:37
  • 1
    no longer works for iOS14 - The `picker.preferredDatePickerStyle = .wheels` does work - but what about color change ??? – iKK Oct 07 '20 at 15:02
24

As of Swift 2.1:

picker.setValue(UIColor.whiteColor(), forKey: "textColor")
picker.sendAction("setHighlightsToday:", to: nil, forEvent: nil)
let date = NSDate()
picker.setDate(date, animated: false)

Instead of "today" you will see the current day,

theDC
  • 6,364
  • 10
  • 56
  • 98
  • 2
    `setHighlightsToday` causes a warning, `No method declared with Objective-C selector 'setHighlightsToday:'` – Daniel Storm Jun 24 '16 at 02:08
  • 2
    Swift 3: picker.setValue(UIColor.white, forKey: "textColor") picker.sendAction(Selector(("setHighlightsToday:")), to: nil, for: nil) – david72 Dec 05 '16 at 21:34
  • In Xcode12/Swift 5.3 `…Selector(("setHighlightsToday:"))…` needs to drop `:` to be `…Selector(("setHighlightsToday"))…` to not have a runtime crash. – marc-medley Dec 11 '20 at 00:58
24

One other alternative to @Jeremiah answer is to define those values in Interface Builder. I prefer this one because there is no code to add in your ViewController.

Click into your DatePicker view and customise it from the Attribute inspector as in the screenshot. screenshot

Works for Swift 2, 3, 4 and probably for Swift < 2. (not tested)

Toldy
  • 1,241
  • 1
  • 14
  • 27
  • 1
    Unfortunately this only colors the word "Today"... and nothing else. And if you set the highlightsToday off, the textColor has no effect. This is in Xcode 11. – Oscar Nov 21 '19 at 09:43
20

Next solution comes from "arturgrigor" and it works great in my apps, just copy it, paste it in viewDidLoad method, and enjoy it :

[my_datePicker setValue:[UIColor whiteColor] forKeyPath:@"textColor"];
SEL selector = NSSelectorFromString( @"setHighlightsToday:" );
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature :
                           [UIDatePicker 
                            instanceMethodSignatureForSelector:selector]];
BOOL no = NO;
[invocation setSelector:selector];
[invocation setArgument:&no atIndex:2];
[invocation invokeWithTarget:my_datePicker];
9

According to Apple's UIKit User Interface Catalog, developers are not allowed to customize date pickers.

I've seen other StackOverflow answers for similar questions that suggest making a fake UIDatePicker using UIPickerView and customizing that.

I also found an open source date picker on GitHub (at https://github.com/mwermuth/MWDatePicker ) that might help a bit. It allows for different background and selector styles, but not a different font or font attributes.... yet.

Michael Dautermann
  • 88,797
  • 17
  • 166
  • 215
  • Thanks Michael. I checked out the MWDatePicker, but it looks like it hasn't been updated for iOS 7 yet. It's just a blank picker when I run the sample project. I've settled for making a simulating a UIDatePicker by customizing a UIPicker. Thanks for the help. It's still very surprising Apple does not allow the customization of a date picker. I wonder why that is? – Milo Jan 02 '14 at 04:34
  • I see there's a [pull request](https://github.com/mwermuth/MWDatePicker/pulls) open to modernize MWDatePicker to iOS 7. It would be good if the owner merged it, but at least you can grab it and make use of it. – Michael Dautermann Nov 16 '14 at 21:27
6

To change UIDatePicker text color use:

    // MARK: - Helping content 

    private enum DatePickerProperties: String {
        case TextColor = "textColor"
        case HighlightsToday = "highlightsToday"
    }

    // MARK: - Outlets

    @IBOutlet private weak var datePicker: UIDatePicker!

    // MARK: - Lifecicle

    public override func awakeFromNib() {
        super.awakeFromNib()

        self.datePicker.setValue(UIColor.whiteColor(), forKey: DatePickerProperties.TextColor.rawValue)
        self.datePicker.setValue(false, forKey: DatePickerProperties.HighlightsToday.rawValue)
    }

It works like a charm with xCode 7.3 and Swift 2.3.

Daniel Sumara
  • 2,234
  • 20
  • 25
6

I stumbled upon a surprisingly clean solution using UIAppearance, without using any KVC, swizzling, or otherwise private API. I found that attempting to set the textColor via UIAppearance for any UILabel within a UIDatePicker had no affect, but a custom appearance property that simply called the regular textColor setter worked just fine.

// Implement a custom appearance property via a UILabel category
@interface UILabel (PickerLabelTextColor)

@property (nonatomic, strong) UIColor * textColorWorkaround UI_APPEARANCE_SELECTOR;

@end

@implementation UILabel (PickerLabelTextColor)

- (UIColor *)textColorWorkaround {
    return self.textColor;
}

- (void)setTextColorWorkaround:(UIColor *)textColor {
    self.textColor = textColor;
}

@end

And then use as follows:

UILabel *pickerLabelProxy = [UILabel appearanceWhenContainedInInstancesOfClasses:@[UIDatePicker.class]];
pickerLabelProxy.textColorWorkaround = UIColor.lightGrayColor;

Swift Version

UILabel extension:

extension UILabel {
    @objc dynamic var textColorWorkaround: UIColor? {
        get {
            return textColor
        }
        set {
            textColor = newValue
        }
    }
}

Appearance proxy use:

let pickerLabelProxy = UILabel.appearance(whenContainedInInstancesOf: [UIDatePicker.self])
pickerLabelProxy.textColorWorkaround = UIColor.lightGray
gyratory circus
  • 437
  • 6
  • 15
  • Can you provide a swift version of this solution please – keegan3d Jul 02 '20 at 16:50
  • @keegan3d Added! It compiles and should be functionally equivalent, but I haven't used this strategy recently. Let us know if it still works! – gyratory circus Jul 03 '20 at 18:03
  • I'm trying it now in iOS 16.5.1 and it works really well when the component first appears, but changing the highlighted digits, and then moving to another, the previously highlighted one reverts to white, same thing with panning screens at a time or rolling the wheels. – clearlight Jul 17 '23 at 09:46
  • It still works in August, 2023 – Carl Smith Aug 10 '23 at 18:13
4

If anyone wants the swift solution, I placed the following in viewDidLoad:

    birthdayDatePicker.setValue(DesignHelper.getOffWhiteColor(), forKey: "textColor")
    birthdayDatePicker.performSelector("setHighlightsToday:", withObject:DesignHelper.getOffWhiteColor())
Jeremiah
  • 1,471
  • 1
  • 13
  • 22
  • great!, any solution for Swift < 2? performSelector isn't available in 1.2 – Dima Deplov Oct 16 '15 at 02:28
  • 1
    anyway to remove the warning in xcode 7.3 - No method declared with Objective-C selector "setHighlightsToday:" ? – user2643679 Mar 24 '16 at 12:22
  • I haven't found one. I've confirmed it works and is still needed. If anyone has a way to do this without getting a warning that would be awesome! – Jeremiah Mar 25 '16 at 20:37
  • To suppress warnings check out this solution http://stackoverflow.com/questions/194666/is-there-a-way-to-suppress-warnings-in-xcode – Fraser Mar 31 '16 at 00:14
4

For Xamarin developers:

DatePicker.SetValueForKey(UIColor.White, new NSString("textColor"));
DatePicker.SetValueForKey(FromObject(false), new NSString("highlightsToday"));

It´s working like a charm. Tested in iOS 9 and 10

xleon
  • 6,201
  • 3
  • 36
  • 52
3

You can also add this as an IBDesignable if you want to configure this within InterFace Builder.

    import UIKit

@IBDesignable
extension UIDatePicker {
    @IBInspectable var textLabelColor: UIColor? {
        get {
            return self.valueForKey("textColor") as? UIColor
        }
        set {
            self.setValue(newValue, forKey: "textColor")
            self.performSelector("setHighlightsToday:", withObject:newValue) //For some reason this line makes the highlighted text appear the same color but can not be changed from textColor. 
        }
    }
}
BandoKal
  • 396
  • 1
  • 5
2

This subclass of UIDatePicker works for iOS 7. Its not pretty but gets the job done.

#define kNotification_UIView_didAddSubview @"kNotification_UIView_didAddSubview"
@implementation UIView (addSubview)

-(void) didAddSubview:(UIView *)subview{
    [[NSNotificationCenter defaultCenter] postNotificationName:kNotification_UIView_didAddSubview object:self];
}
@end


@interface DatePicker ()
@property (nonatomic, strong) UIColor* textColor;
@end

@implementation DatePicker

-(id) initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self){
        [self setup];
    }
    return self;
}
-(id) initWithCoder:(NSCoder *)aDecoder{
    self = [super initWithCoder:aDecoder];
    if (self){
        [self setup];
    }
    return self;
}

-(void) setup{
    self.textColor = [UIColor darkTextColor];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(subviewsUpdated:) name:kNotification_UIView_didAddSubview object:nil];
}

-(void) dealloc{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

-(void) updateLabels:(UIView*) view{
    for (UILabel* label in view.subviews){
        if ([label isKindOfClass:[UILabel class]]){
            label.textColor = self.textColor;
        }else{
            [self updateLabels:label];
        }
    }
}

-(BOOL) isSubview:(UIView*) view{
    if (view == nil){
        return NO;
    }
    if (view.superview == self){
        return YES;
    }
    return [self isSubview:view.superview];
}

-(void) subviewsUpdated:(NSNotification*) notification{
    if ([notification.object isKindOfClass:NSClassFromString(@"UIPickerTableView")] && [self isSubview:notification.object]){
        [self updateLabels:notification.object];
    }
}

@end
datinc
  • 3,404
  • 3
  • 24
  • 33
2
[date_picker setValue:textColor forKey:@"textColor"];
[date_picker performSelector:@selector(setHighlightsToday:) withObject:NO];
Srj0x0
  • 458
  • 3
  • 12
2

Add Runtime Attribute named "textColor" from Storyboard as shown in following image.

enter image description here

Mehul Thakkar
  • 12,440
  • 10
  • 52
  • 81
1

As alternative to @Jeremiah answer, you can use this:

datePicker.setValue(UIColor.redColor(), forKey: "textColor")
datePicker.sendAction("setHighlightsToday:", to: nil, forEvent: nil)
datePicker.setDate(NSDate(timeIntervalSinceReferenceDate: 0), animated: false)

it will remove Today (you will see current date), but it will be with right color.

Possible troubles: if you change color dynamically, I didn't find a way to reload date picker. So, the user will see previous color and only after scroll, color will changed to a new one. -> Solved, by last string. Looks like Voodoo, but it works...

This answer suitable for Swift 2.1

Dima Deplov
  • 3,688
  • 7
  • 45
  • 77
1

It didn't work until textColor was set inside layoutSubviews()

override func layoutSubviews() {
    super.layoutSubviews()
    datePicker.backgroundColor = .black
    datePicker.setValue(.white, forKeyPath: "textColor")
}
Bassant Ashraf
  • 1,531
  • 2
  • 16
  • 23
0

Just use datePicker.tintColor = .red or any other color you want.

Boris Nikolic
  • 746
  • 14
  • 24
0
[my_date_picker setValue:[UIColor whiteColor] forKey:@"textColor"];

it seems don't work on ios 13 or later, you can set overrideUserInterfaceStyle property for UIDatePicker to determin it shows white color or black.