我可以在 iOS7 中更改 datePicker 的字体颜色吗?

Posted

技术标签:

【中文标题】我可以在 iOS7 中更改 datePicker 的字体颜色吗?【英文标题】:can I change the font color of the datePicker in iOS7? 【发布时间】:2013-09-19 10:01:42 【问题描述】:

刚刚下载了我的 xcode 5 副本,想知道是否有人知道我可以如何更改日期选择器中字体的颜色或大小?

【问题讨论】:

我面临同样的问题......你是如何解决 UIDatePicker 而不是 UIPicker 的 Custom ios UIDatepicker using UIAppearance的可能重复 ***.com/questions/19232817/…的可能重复 上色很简单:***.com/a/31775498/3052059 【参考方案1】:

我的应用需要类似的东西,并且最终走了很长一段路。真的很遗憾,没有更简单的方法可以简单地切换到 UIDatePicker 的白色文本版本。

当 setTextColor: 消息发送到标签时,下面的代码使用 UILabel 上的类别来强制标签的文本颜色为白色。为了不对应用程序中的每个标签执行此操作,我将其过滤为仅在它是 UIDatePicker 类的子视图时应用。最后,一些标签在添加到它们的超级视图之前设置了它们的颜色。为了捕捉这些,代码会覆盖 willMoveToSuperview: 方法。

最好将以下内容拆分为多个类别,但为了便于发布,我已将其全部添加到此处。

#import "UILabel+WhiteUIDatePickerLabels.h"
#import <objc/runtime.h>

@implementation UILabel (WhiteUIDatePickerLabels)

+ (void)load 
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^
        [self swizzleInstanceSelector:@selector(setTextColor:)
                      withNewSelector:@selector(swizzledSetTextColor:)];
        [self swizzleInstanceSelector:@selector(willMoveToSuperview:)
                      withNewSelector:@selector(swizzledWillMoveToSuperview:)];
    );


// Forces the text colour of the label to be white only for UIDatePicker and its components
-(void) swizzledSetTextColor:(UIColor *)textColor 
    if([self view:self hasSuperviewOfClass:[UIDatePicker class]] ||
       [self view:self hasSuperviewOfClass:NSClassFromString(@"UIDatePickerWeekMonthDayView")] ||
       [self view:self hasSuperviewOfClass:NSClassFromString(@"UIDatePickerContentView")])
        [self swizzledSetTextColor:[UIColor whiteColor]];
     else 
        //Carry on with the default
        [self swizzledSetTextColor:textColor];
    


// Some of the UILabels haven't been added to a superview yet so listen for when they do.
- (void) swizzledWillMoveToSuperview:(UIView *)newSuperview 
    [self swizzledSetTextColor:self.textColor];
    [self swizzledWillMoveToSuperview:newSuperview];


// -- helpers --
- (BOOL) view:(UIView *) view hasSuperviewOfClass:(Class) class 
    if(view.superview)
        if ([view.superview isKindOfClass:class])
            return true;
        
        return [self view:view.superview hasSuperviewOfClass:class];
    
    return false;


+ (void) swizzleInstanceSelector:(SEL)originalSelector
                 withNewSelector:(SEL)newSelector

    Method originalMethod = class_getInstanceMethod(self, originalSelector);
    Method newMethod = class_getInstanceMethod(self, newSelector);

    BOOL methodAdded = class_addMethod([self class],
                                       originalSelector,
                                       method_getImplementation(newMethod),
                                       method_getTypeEncoding(newMethod));

    if (methodAdded) 
        class_replaceMethod([self class],
                            newSelector,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
     else 
        method_exchangeImplementations(originalMethod, newMethod);
    


@end

【讨论】:

这个解决方案比“滚动你自己”的解决方案更好,因为它保留了区域设置。 +1 只是为了使用 swizzling。我想从技术上讲,这甚至没有使用任何私有 API。 真的很好。工作得很好,可以快速添加。我从来没有时间花时间自己解决这个问题。谢谢!它应该得到复选标记。 此解决方案能否通过 App Store 审核?有人试过吗? 此解决方案能否通过 App Store 审核?有人试过吗?【参考方案2】:

这是最简单的方法,而且很有效!我承诺。在视图中创建UIDatePicker,或者通过storyboard连接,然后将如下代码放入ViewDidLoad方法中。将第一行中的“datepicker”替换为您命名的日期选择器。

目标-C:

//Set Color of Date Picker
self.datePicker.datePickerMode = UIDatePickerModeDate;
[self.datePicker setValue:[UIColor colorWithRed:70/255.0f green:161/255.0f blue:174/255.0f alpha:1.0f] 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:self.datePicker];

【讨论】:

我在这方面花了很多时间,这是唯一适用于UIDatePicker 实例的方法。 如何更改 UIDatePicker 中的字体? @TriannaBrannon 看起来 NSInvocation 很快就消失了:https://developer.apple.com/swift/blog/?id=19 因此没有编译。 在斯威夫特datePicker.setValue(UIColor.whiteColor(), forKey: "textColor") datePicker.setValue(false, forKey: "highlightsToday")【参考方案3】:

我继续使用 UIControlUIPicker 为 iOS 7 实现了 UIDatePicker 替换。这使您可以编辑所需的所有内容,包括文本字体和颜色。 我唯一无法更改的是所选行周围线条的颜色。

有些事情可以进一步简化,它只显示日期,而不是时间。这可以作为任何想做类似事情的人的起点。

@interface SBDatePicker : UIControl

@property (nonatomic, strong, readwrite) NSDate *minimumDate;
@property (nonatomic, strong, readwrite) NSDate *maximumDate;
@property (nonatomic, strong, readwrite) NSDate *date;

- (void)setDate:(NSDate *)date animated:(BOOL)animated;

@end

#import "SBDatePicker.h"

const NSUInteger NUM_COMPONENTS = 3;

typedef enum 
    kSBDatePickerInvalid = 0,
    kSBDatePickerYear,
    kSBDatePickerMonth,
    kSBDatePickerDay
 SBDatePickerComponent;

@interface SBDatePicker () <UIPickerViewDataSource, UIPickerViewDelegate> 
    SBDatePickerComponent _components[NUM_COMPONENTS];


@property (nonatomic, strong, readwrite) NSCalendar *calendar;
@property (nonatomic, weak, readwrite) UIPickerView *picker;

@property (nonatomic, strong, readwrite) NSDateFormatter *dateFormatter;

@property (nonatomic, strong, readwrite) NSDateComponents *currentDateComponents;

@property (nonatomic, strong, readwrite) UIFont *font;

@end

@implementation SBDatePicker

#pragma mark - Life cycle

- (id)initWithFrame:(CGRect)frame 
    self = [super initWithFrame:frame];

    if (!self) 
        return nil;
    

    [self commonInit];

    return self;


- (id)initWithCoder:(NSCoder *)coder 
    self = [super initWithCoder:coder];

    if (!self) 
        return nil;
    

    [self commonInit];

    return self;


- (void)commonInit 
    self.tintColor = [UIColor whiteColor];
    self.font = [UIFont systemFontOfSize:23.0f];

    self.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    [self setLocale:[NSLocale currentLocale]];

    UIPickerView *picker = [[UIPickerView alloc] initWithFrame:self.bounds];
    picker.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
    picker.dataSource = self;
    picker.delegate = self;
    picker.tintColor = [UIColor whiteColor];

    self.date = [NSDate date];

    [self addSubview:picker];
    self.picker = picker;


- (CGSize)intrinsicContentSize 
    return CGSizeMake(320.0f, 216.0f);


#pragma mark - Setup

- (void)setMinimumDate:(NSDate *)minimumDate 
    _minimumDate = minimumDate;

    [self updateComponents];


- (void)setMaximumDate:(NSDate *)maximumDate 
    _maximumDate = maximumDate;

    [self updateComponents];


- (void)setDate:(NSDate *)date 
    [self setDate:date animated:NO];


- (void)setDate:(NSDate *)date animated:(BOOL)animated 
    self.currentDateComponents = [self.calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
                                                  fromDate:date];

    [self.picker reloadAllComponents];
    [self setIndicesAnimated:YES];


- (NSDate *)date 
    return [self.calendar dateFromComponents:self.currentDateComponents];


- (void)setLocale:(NSLocale *)locale 
    self.calendar.locale = locale;

    [self updateComponents];


- (SBDatePickerComponent)componentFromLetter:(NSString *)letter 
    if ([letter isEqualToString:@"y"]) 
        return kSBDatePickerYear;
    
    else if ([letter isEqualToString:@"m"]) 
        return kSBDatePickerMonth;
    
    else if ([letter isEqualToString:@"d"]) 
        return kSBDatePickerDay;
    
    else 
        return kSBDatePickerInvalid;
    


- (SBDatePickerComponent)thirdComponentFromFirstComponent:(SBDatePickerComponent)component1
                                       andSecondComponent:(SBDatePickerComponent)component2 

    NSMutableIndexSet *set = [NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(kSBDatePickerInvalid + 1, NUM_COMPONENTS)];
    [set removeIndex:component1];
    [set removeIndex:component2];

    return (SBDatePickerComponent) [set firstIndex];


- (void)updateComponents 
    NSString *componentsOrdering = [NSDateFormatter dateFormatFromTemplate:@"yMMMMd" options:0 locale:self.calendar.locale];
    componentsOrdering = [componentsOrdering lowercaseString];

    NSString *firstLetter = [componentsOrdering substringToIndex:1];
    NSString *lastLetter = [componentsOrdering substringFromIndex:(componentsOrdering.length - 1)];

    _components[0] = [self componentFromLetter:firstLetter];
    _components[2] = [self componentFromLetter:lastLetter];
    _components[1] = [self thirdComponentFromFirstComponent:_components[0] andSecondComponent:_components[2]];

    self.dateFormatter = [[NSDateFormatter alloc] init];
    self.dateFormatter.calendar = self.calendar;
    self.dateFormatter.locale = self.calendar.locale;

    [self.picker reloadAllComponents];

    [self setIndicesAnimated:NO];


- (void)setIndexForComponentIndex:(NSUInteger)componentIndex animated:(BOOL)animated 
    SBDatePickerComponent component = [self componentForIndex:componentIndex];
    NSRange unitRange = [self rangeForComponent:component];

    NSInteger value;

    if (component == kSBDatePickerYear) 
        value = self.currentDateComponents.year;
    
    else if (component == kSBDatePickerMonth) 
        value = self.currentDateComponents.month;
    
    else if (component == kSBDatePickerDay) 
        value = self.currentDateComponents.day;
    
    else 
        assert(NO);
    

    NSInteger index = (value - unitRange.location);
    NSInteger middleIndex = (INT16_MAX / 2) - (INT16_MAX / 2) % unitRange.length + index;

    [self.picker selectRow:middleIndex inComponent:componentIndex animated:animated];


- (void)setIndicesAnimated:(BOOL)animated 
    for (NSUInteger componentIndex = 0; componentIndex < NUM_COMPONENTS; componentIndex++) 
        [self setIndexForComponentIndex:componentIndex animated:animated];
    


- (SBDatePickerComponent)componentForIndex:(NSInteger)componentIndex 
    return _components[componentIndex];


- (NSCalendarUnit)unitForComponent:(SBDatePickerComponent)component 
    if (component == kSBDatePickerYear) 
        return NSYearCalendarUnit;
    
    else if (component == kSBDatePickerMonth) 
        return NSMonthCalendarUnit;
    
    else if (component == kSBDatePickerDay) 
        return NSDayCalendarUnit;
    
    else 
        assert(NO);
    


- (NSRange)rangeForComponent:(SBDatePickerComponent)component 
    NSCalendarUnit unit = [self unitForComponent:component];

    return [self.calendar maximumRangeOfUnit:unit];


#pragma mark - Data source

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView 
    return 3;


- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)componentIndex 
    return INT16_MAX;


#pragma mark - Delegate

- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)componentIndex 
    SBDatePickerComponent component = [self componentForIndex:componentIndex];

    if (component == kSBDatePickerYear) 
        CGSize size = [@"0000" sizeWithAttributes:@NSFontAttributeName : self.font];

        return size.width + 25.0f;
    
    else if (component == kSBDatePickerMonth) 
        CGFloat maxWidth = 0.0f;

        for (NSString *monthName in self.dateFormatter.monthSymbols) 
            CGFloat monthWidth = [monthName sizeWithAttributes:@NSFontAttributeName : self.font].width;

            maxWidth = MAX(monthWidth, maxWidth);
        

        return maxWidth + 25.0f;
    
    else if (component == kSBDatePickerDay) 
        CGSize size = [@"00" sizeWithAttributes:@NSFontAttributeName : self.font];

        return size.width + 25.0f;
    
    else 
        return 0.01f;
    


- (NSString *)titleForRow:(NSInteger)row forComponent:(SBDatePickerComponent)component 
    NSRange unitRange = [self rangeForComponent:component];
    NSInteger value = unitRange.location + (row % unitRange.length);

    if (component == kSBDatePickerYear) 
        return [NSString stringWithFormat:@"%li", (long) value];
    
    else if (component == kSBDatePickerMonth) 
        return [self.dateFormatter.monthSymbols objectAtIndex:(value - 1)];
    
    else if (component == kSBDatePickerDay) 
        return [NSString stringWithFormat:@"%li", (long) value];
    
    else 
        return @"";
    


- (NSInteger)valueForRow:(NSInteger)row andComponent:(SBDatePickerComponent)component 
    NSRange unitRange = [self rangeForComponent:component];

    return (row % unitRange.length) + unitRange.location;


- (BOOL)isEnabledRow:(NSInteger)row forComponent:(NSInteger)componentIndex 
    NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
    dateComponents.year = self.currentDateComponents.year;
    dateComponents.month = self.currentDateComponents.month;
    dateComponents.day = self.currentDateComponents.day;

    SBDatePickerComponent component = [self componentForIndex:componentIndex];
    NSInteger value = [self valueForRow:row andComponent:component];

    if (component == kSBDatePickerYear) 
        dateComponents.year = value;
    
    else if (component == kSBDatePickerMonth) 
        dateComponents.month = value;
    
    else if (component == kSBDatePickerDay) 
        dateComponents.day = value;
    

    NSDate *rowDate = [self.calendar dateFromComponents:dateComponents];

    if (self.minimumDate != nil && [self.minimumDate compare:rowDate] == NSOrderedDescending) 
        return NO;
    
    else if (self.maximumDate != nil && [rowDate compare:self.maximumDate] == NSOrderedDescending) 
        return NO;
    

    return YES;


- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)componentIndex reusingView:(UIView *)view 
    UILabel *label;

    if ([view isKindOfClass:[UILabel class]]) 
        label = (UILabel *) view;
    
    else 
        label = [[UILabel alloc] init];
        label.font = self.font;
    

    SBDatePickerComponent component = [self componentForIndex:componentIndex];
    NSString *title = [self titleForRow:row forComponent:component];

    UIColor *color;

    BOOL enabled = [self isEnabledRow:row forComponent:componentIndex];

    if (enabled) 
        color = [UIColor whiteColor];
    
    else 
        color = [UIColor colorWithWhite:0.0f alpha:0.5f];
    

    NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString:title
attributes:@NSForegroundColorAttributeName: color];

    label.attributedText = attributedTitle;

    if (component == kSBDatePickerMonth) 
        label.textAlignment = NSTextAlignmentLeft;
    
    else 
        label.textAlignment = NSTextAlignmentRight;
    

    return label;


- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)componentIndex 
    SBDatePickerComponent component = [self componentForIndex:componentIndex];
    NSInteger value = [self valueForRow:row andComponent:component];

    if (component == kSBDatePickerYear) 
        self.currentDateComponents.year = value;
    
    else if (component == kSBDatePickerMonth) 
        self.currentDateComponents.month = value;
    
    else if (component == kSBDatePickerDay) 
        self.currentDateComponents.day = value;
    
    else 
        assert(NO);
    

    [self setIndexForComponentIndex:componentIndex animated:NO];

    NSDate *datePicked = self.date;

    if (self.minimumDate != nil && [datePicked compare:self.minimumDate] == NSOrderedAscending) 
        [self setDate:self.minimumDate animated:YES];
    
    else if (self.maximumDate != nil && [datePicked compare:self.maximumDate] == NSOrderedDescending) 
        [self setDate:self.maximumDate animated:YES];
    
    else 
        [self.picker reloadAllComponents];
    

    [self sendActionsForControlEvents:UIControlEventValueChanged];


@end

【讨论】:

你也有#import "NSMutableAttributedString+Append.h" 代码吗? 哦,这只是我用来创建属性字符串的一个简单类别。这里不需要。我将从源头中删除它。 没有它,它似乎不起作用!调用 [attributedTitle appendString:title withColor:color];一些帮助将不胜感激。 好吧,算了吧……我已经想通了,只是做了一些微小的改动。谢谢它有效。 哦。手动引用计数。花式;)非常感谢!【参考方案4】:

我也在为此苦苦挣扎,黑色背景上的黑色文字。 :) 我还没有找到改变文本颜色的方法。 但是,您可以使用背景颜色:

picker.backgroundColor = [UIColor whiteColor];

我发现另一个可行的方法是在日期选择器中提供每个 UIView(每个数字都有自己的 UIView,(是的,我知道)

[UIView appearanceWhenContainedIn:[UITableView class], [UIDatePicker class], nil].backgroundColor = [UIColor colorWithWhite:1 alpha:0.5]

(我不建议使用此选项,因为它会在旋转时产生烦人的闪烁效果。)

希望这会有所帮助。 :)

【讨论】:

【参考方案5】:

在 viewDidLoad 中,

datePicker.setValue(UIColor.yellowColor(), forKey: "textColor")
datePicker.performSelector("setHighlightsToday:", withObject:UIColor.yellowColor())

适用于 iOS 9

【讨论】:

前一个有效,后一个无效 Xcode 7.3.1, iOS 9.3 下一个抛出异常。【参考方案6】:

有点老套,但话又说回来,所有其他解决方案也是如此。这对我有用:子类 UIDatePicker 并在向其添加任何视图之前更改 textColor 属性的值。

只改变颜色:

class ColoredDatePicker: UIDatePicker 
    var changed = false
    override func addSubview(view: UIView) 
        if !changed 
            changed = true
            self.setValue(yourColor, forKey: "textColor")
        
        super.addSubview(view)
    

改变颜色和其他属性:

如果我解决了这个问题,我会更新。

我确实注意到颜色并没有完全按照颜色对象的指示来表示,但可以尝试一下,让它成为你想要的颜色。

【讨论】:

我想要的只是白色,这对我来说非常合适。谢谢!【参考方案7】:

我在这里回答了一个类似的问题:UIPickerView Custom Fonts iOS7 基本上你必须破解 viewForRow: 方法,而现在我只让它适用于 UIPickerView 而不是 UIDatePickers。 (正在努力……)

-(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view

以下是 UIPickerView 显示属性文本(自定义字体、颜色等)的方式

-(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view

// create attributed string
NSString *yourString;  //can also use array[row] to get string
NSDictionary *attributeDict = @NSForegroundColorAttributeName : [UIColor whiteColor];
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:yourString attributes:attributeDict];

// add the string to a label's attributedText property
UILabel *labelView = [[UILabel alloc] init];
labelView.attributedText = attributedString;

// return the label
return labelView;

希望对您有所帮助...我会在找到日期选择器后立即编辑我的答案!

【讨论】:

这方面有进展吗?【参考方案8】:

这适用于 iOS 9

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

【讨论】:

它不能直接工作..一旦我们滚动选择器它就会工作【参考方案9】:

您可以在 swift 中将这两行添加到您的 viewDidLoad:

    datePicker.setValue(DesignHelper.getOffWhiteColor(), forKey: "textColor")
    datePicker.performSelector("setHighlightsToday:", withObject: UIColor.whiteColor())

【讨论】:

DesignHelper 从何而来? 糟糕,忽略它。这是一个返回 UIColor 的自定义类 我用 UIColor.redColor() 试过了,但是没用【参考方案10】:

我偶然发现了一个使用UIAppearance 的非常干净的解决方案。我发现尝试通过UIAppearanceUILabel 中的UIPickerView 设置textColor 没有任何影响,但是简单地称为常规textColor 设置器的自定义外观属性工作得很好。

// 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

然后按如下方式使用:

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

【讨论】:

【参考方案11】:
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, pickerView.frame.size.width, 44)];
label.backgroundColor = [UIColor grayColor];
label.textColor = [UIColor whiteColor];
label.font = [UIFont fontWithName:@"HelveticaNeue-Bold" size:18];
label.text = [NSString stringWithFormat:@" %d", row+1];
return label;    


// number Of Components
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
return 1;


// number Of Rows In Component
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:   (NSInteger)component
return 6;

【讨论】:

请添加一些解释以配合您的答案中的代码。 -1 因为代码没有解释。我们应该继承UIDatePicker 还是什么? 当我用于日期选择器时,不会调用此代码...这仅适用于 UIPicker,不适用于 UIDatePicker 这对 UIPicker 很有效,不过解释会很好。 这是为 PickerView.. 不是为 DatePicker

以上是关于我可以在 iOS7 中更改 datePicker 的字体颜色吗?的主要内容,如果未能解决你的问题,请参考以下文章

更改日期选择器的文本颜色

在 WPF 中更改 Material Design DatePicker 的外观

DatePicker 更改自定义标题中的视图

在 Jquery Datepicker 中动态更改突出显示的日期

在运行中以编程方式更改 iOS7 状态栏颜色?

在 Modelpopup 文本框中更改 Datepicker 的位置