it-swarm.com.ru

я могу изменить цвет шрифта datePicker в iOS7?

только что скачал мою копию xcode 5 и мне стало интересно, кто-нибудь знает, как я могу изменить цвет или размер шрифта в средстве выбора даты?

36
Jared Gross

Мне нужно подобное для моего приложения, и в итоге я прошел долгий путь. Жаль, что нет более простого способа просто перейти на белую текстовую версию UIDatePicker. 

Приведенный ниже код использует категорию на UILabel, чтобы цвет текста метки был белым, когда на метку отправлено сообщение setTextColor :. Чтобы этого не делать для каждого ярлыка в приложении, я отфильтровал его, чтобы он применялся только в том случае, если это подпредставление класса 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
59
Sig

Это самый простой способ, и он работает! Я обещаю. Создайте UIDatePicker в представлении или подключите его через раскадровку, а затем вставьте следующий код в метод ViewDidLoad. Замените «datepicker» в первой строке на то, что вы называете «datepicker».

Objective-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];
41
Trianna Brannon

Msgstr "Вы не можете настроить внешний вид сборщиков даты".

См. IOS 7 Design Resources/Каталог пользовательского интерфейса UIKit/Выбор даты

28
chrisinsfo

Я продолжил и реализовал замену UIDatePicker, используя UIControl и UIPicker для iOS 7. Это позволяет вам редактировать все, что вы хотите, включая текстовые шрифты и цвета .. Единственное, что я не смог изменить, - это цвет линий вокруг выбранная строка.

Есть вещи, которые можно было бы еще больше упростить, и они отображают только дату, а не время. Это может послужить отправной точкой для тех, кто хочет сделать что-то подобное.

enter image description here

@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
26
Sulthan

В viewDidLoad,

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

Работа на iOS 9

10
user2643679

Я тоже с этим борюсь, черный текст на черном фоне. :) Я еще не нашел способ изменить цвет текста . Однако вы можете поиграть с цветом фона:

picker.backgroundColor = [UIColor whiteColor];

Еще один хак, который я нашел, работал: каждый UIView указывается в DatePicker (каждый номер имеет свой собственный UIView, (да, я знаю)

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

(Я не рекомендую использовать эту опцию, поскольку она вызывает раздражающий эффект мерцания при вращении.)

Надеюсь это поможет. :)

10
JoriDor

Немного хакерский, но опять же, как и все другие решения. Это сработало для меня: создайте подкласс 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)
    }
}

Чтобы изменить цвет и другие атрибуты:

Я обновлю, если выясню это.

Я замечаю, что цвет представлен не совсем так, как диктует цветовой объект, но поиграйте с ним и получите желаемый цвет.

6
Eric F.

Я ответил на аналогичный вопрос здесь: 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;

}

Надеюсь, что это поможет ... Я отредактирую свой ответ, как только выясню Сборщика Даты!

4
self.name

В Swift вы можете добавить эти две строки в ваш viewDidLoad:

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

Это работает в iOS 9

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

Я наткнулся на удивительно чистое решение, используя UIAppearance. Я обнаружил, что попытка установить textColor через UIAppearance для любого UILabel внутри UIPickerView не имела никакого эффекта, но свойство пользовательского внешнего вида, которое просто вызывало обычный установщик 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;
0
gyratory circus