Настроить цвет текста UIDatePicker для iOS7 (как и в случае с почтовым ящиком)
У меня самая неприятная дилемма. Я исследовал вверх и вниз и могу ясно видеть, что Apple не хочет, чтобы мы подделывали iOS 7. Ну, я хочу вмешаться. И команда в Mailbox ясно поняла, как это сделать и получить одобрение.
Главное, что я пытаюсь добиться, - изменить цвет ярлыка на белый.
![Mailbox UIDatePicker]()
Моя первая мысль заключалась в том, что они используют пользовательский UIPickerView, который просто имитирует UIDatePicker, но я просто не думаю, что это так.
Я увеличил малый фрагмент и обнаружил остатки обычного UIDatePicker (черные линии) вместе с отсечением на букву "W".
![Mailbox UIDatePicker fragments]()
Теперь я пробирался высоко и низко. Произошел какой-то хакерский хакер, запутался в UIAppearance и даже выкопал некоторые частные API, чтобы убедиться, что это возможно.
У меня был близкий, очень близкий, но он использовал частный API, и если вы прокручиваете достаточно быстро, ярлыки снова станут черными.
Я полностью в недоумении о том, как это сделать, не нарушая правил или б) потратив бесчисленные часы на повторную реализацию UIDatePicker.
Почтовый ящик, расскажи мне свои секреты! И если у кого-нибудь есть предложения (и я имею в виду любые), пожалуйста, дайте мне знать.
Кроме того, это ближайший я получил:
![So close yet so far]()
Ответы
Ответ 1
Мне нужно подобное для моего приложения и закончилось тем, что продолжалось. Это настоящий позор, когда нет простого способа перейти к белой текстовой версии 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 lable 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
Ответ 2
Вот хороший рабочий фрагмент. Протестировано на iOS 7.1, 8.0 и 8.1.
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_8_1
#error "Check if this hack works on this OS"
#endif
[self.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:self.datePicker];
Я добавил простое условие для разрыва процесса компиляции, если вы создаете для iOS > 8.1, потому что я не могу быть уверен, что этот хак будет работать, а вы не из-за этого вы хотите иметь какие-либо сбои в производстве.
Селектор setHighlightsToday:
используется, поскольку UIDatePicker
использует [UIColor blackColor]
по умолчанию для отображения текущей даты.
Ответ 3
Я нашел трюк, который задал цвет шрифта любому цвету, а также не испортил ярлык Today.
datePicker.setValue(UIColor.whiteColor(), forKeyPath: "textColor")
datePicker.datePickerMode = .CountDownTimer
datePicker.datePickerMode = .DateAndTime //or whatever your original mode was
Вот результат:
![rNJe7.png]()
И все кредиты для этого решения идут на этот пост в другой теме:
fooobar.com/questions/147895/...
Ответ 4
self.birthDatePicker.setValue(UIColor.whiteColor(), forKeyPath: "textColor")
Это сработало для меня.
Ответ 5
Верный способ сделать это - итерация через subviews и subviews subviews, пока вы не найдете класс, который вы ищете (в данном случае, какой-то UILabel) и вручную установите на нем свойства.
Чтобы найти тот, который вы ищете, я предлагаю вам использовать приложение, такое как X-ray или Reveal, для проверки иерархии представлений, чтобы получить точное имя класса, а затем:
for (UIView * subview in datePicker.subviews) {
if ([subview isKindOfClass:NSClassFromString:@"_UISomePrivateLabelSubclass"]) {
[subview setColor:...
//do interesting stuff here
}
}
Это очень хрупкий способ делать что-то, но технически никогда не называют частный API, и это не пугает Apple. Назад в iOS 5 Я делал такие вещи, чтобы сделать UIAlertViews больше на iPads, чтобы иметь больше текста без встроенного представления прокрутки.
Может потребоваться много проб и ошибок, и может показаться не очень красивым, но оно будет работать.
(Как очень умный парень, которого я знаю, сказал: "весь код будет потерян для компилятора, например, слезы в дождь".)