Milo
Milo

Reputation: 5091

Change UIDatePicker font color?

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?

Upvotes: 46

Views: 50195

Answers (17)

Chao Huang
Chao Huang

Reputation: 1

[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.

Upvotes: 0

Boris Nikolic
Boris Nikolic

Reputation: 756

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

Upvotes: 0

gyratory circus
gyratory circus

Reputation: 447

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

Upvotes: 7

Bassant Ashraf
Bassant Ashraf

Reputation: 1609

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

override func layoutSubviews() {
    super.layoutSubviews()
    datePicker.backgroundColor = .black
    datePicker.setValue(.white, forKeyPath: "textColor")
}

Upvotes: 1

Michael Dautermann
Michael Dautermann

Reputation: 89509

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.

Upvotes: 9

Toldy
Toldy

Reputation: 1251

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)

Upvotes: 25

xleon
xleon

Reputation: 6365

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

Upvotes: 4

waffles
waffles

Reputation: 1396

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

}

Upvotes: 90

Mehul Thakkar
Mehul Thakkar

Reputation: 12594

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

enter image description here

Upvotes: 2

Daniel Sumara
Daniel Sumara

Reputation: 2264

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.

Upvotes: 6

Srj0x0
Srj0x0

Reputation: 456

[date_picker setValue:textColor forKey:@"textColor"];
[date_picker performSelector:@selector(setHighlightsToday:) withObject:NO];

Upvotes: 2

Dima Deplov
Dima Deplov

Reputation: 3718

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

Upvotes: 1

theDC
theDC

Reputation: 6484

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,

Upvotes: 24

Jeremiah
Jeremiah

Reputation: 1461

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

    birthdayDatePicker.setValue(DesignHelper.getOffWhiteColor(), forKey: "textColor")
    birthdayDatePicker.performSelector("setHighlightsToday:", withObject:DesignHelper.getOffWhiteColor())

Upvotes: 4

BandoKal
BandoKal

Reputation: 396

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

Upvotes: 3

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

Upvotes: 20

datinc
datinc

Reputation: 3552

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

Upvotes: 2

Related Questions