自定义iOS7的UIDatePicker的文本颜色(就像邮箱一样)

我有最令人沮丧的困境。 我已经研究了上下,可以清楚地看到,苹果不希望我们篡改iOS 7.嗯,我想篡改。 而且,邮箱的团队清楚地知道如何去做并获得批准。

我试图实现的主要目标是将标签颜色更改为白色。

邮箱UIDatePicker

我的第一个想法是他们正在使用一个自定义UIPickerView只是模仿UIDatePicker,但我不认为这是事实。

我放大了一个小片段,发现了一个正常的UIDatePicker(黑色线条)的残余,并在字母“W”上加上了裁剪。

邮箱UIDatePicker片段

现在我已经高高在上了。 有没有一些运行时间的黑客攻击,与UIAppearance,甚至挖入一些私人的API只是为了看看这是可能的。

我接近,非常接近,但它使用了一个私人的API,如果你滚动得足够快,标签会变黑。

我完全不知道如何做到这一点,没有a)违反规则或b)花费无数小时重新实现UIDatePicker。

邮箱,告诉我你的秘密! 如果其他人有任何build议(我的意思是任何),请让我知道。

另外,这是我得到的最接近的:

到目前为止,还很近

我需要类似于我的应用程序,并最终走了很长的路。 真正的耻辱是没有简单的方法来简单地切换到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 

这是一个很好的工作片段。 在iOS 7.1,8.08.1上testing。

 #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构build,因为我不能确定这个黑客行得通,而且你也不想因为这个而产生任何崩溃。

使用setHighlightsToday:select器是因为UIDatePicker默认使用[UIColor blackColor]显示当前date。

我发现把字体颜色设置为任何颜色的技巧,也不要搞乱Today标签。

 datePicker.setValue(UIColor.whiteColor(), forKeyPath: "textColor") datePicker.datePickerMode = .CountDownTimer datePicker.datePickerMode = .DateAndTime //or whatever your original mode was 

结果如下:

而这个解决scheme的所有功劳都可以在其他主题中find: https : //stackoverflow.com/a/33459744/1236334

 self.birthDatePicker.setValue(UIColor.whiteColor(), forKeyPath: "textColor") 

这对我有效。

这样做的绝对方法是遍历子视图和子视图子视图,直到find要查找的类(在本例中为某种UILabel)并手动设置属性为止。

要find你正在寻找的人,我build议你使用像X射线或显示的应用程序检查视图层次结构来获取确切的类名,然后:

 for (UIView * subview in datePicker.subviews) { if ([subview isKindOfClass:NSClassFromString:@"_UISomePrivateLabelSubclass"]) { [subview setColor:... //do interesting stuff here } } 

这是一个非常脆弱的做事方式,但它从技术上来说并没有称之为私有API,也不会吓倒苹果。 回到iOS 5我曾经做过这样的事情,让iPad上的UIAlertViews更大,让更多的文本没有embedded的滚动视图。

许多试验和错误可能是必要的,它可能看起来不漂亮,但它会工作。

(我知道一个非常聪明的人说:“所有的代码都会丢到编译器上,就像雨中的泪水一样。”)