ios - 为 iOS7 自定义 UIDatePicker 的文本颜色(就像 Mailbox 一样)

标签 ios uikit uipickerview uidatepicker uiappearance

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

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

Mailbox UIDatePicker

我的第一个想法是他们正在使用一个自定义的 UIPickerView,它只是模仿一个 UIDatePicker,但我认为情况并非如此。

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

Mailbox UIDatePicker fragments

现在我已经四处搜寻了。做了一些运行时黑客攻击,弄乱了 UIAppearance,甚至挖掘了一些私有(private) API 只是为了看看这是否可能。

我接近了,非常接近了,但它使用了一个私有(private) API,如果你滚动得足够快,标签会再次变黑。

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

邮箱,告诉我你的 secret !如果其他人有任何建议(我是说任何建议),请告诉我。

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

So close yet so far

最佳答案

我的应用程序需要类似的东西,但最终还是走了很长一段路。很遗憾没有更简单的方法来简单地切换到 UIDatePicker 的白色文本版本。

下面的代码在 UILabel 上使用一个类别,当 setTextColor: 消息发送到标签时,强制标签的文本颜色为白色。为了不对应用程序中的每个标签都执行此操作,我将其过滤为仅在它是 UIDatePicker 类的 subview 时应用。最后,一些标签在添加到它们的 super View 之前设置了颜色。为了捕获这些,代码覆盖了 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 - 为 iOS7 自定义 UIDatePicker 的文本颜色(就像 Mailbox 一样),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20181225/

相关文章:

swift - UITextField + 计时器问题 - 检查 "Editing Changed"但只有一次启动计时器?

iphone - UIPickerView 没有 IB?

iOS Xcode SPM 未能解开父类(super class)

ios - 以模式加载新 View 并保持 gcd 异步代码运行

ios - 在表格 View 中重新加载数据而不损害动画

ios - 如何根据 UIPickerview 中的第一个组件选择设置第二个组件中的数据

iphone - 如何更改 UIPickerView 行中单个字符的字体颜色?

ios - 阻止选择 NSMutableArray 中的某些对象?

iOS layer.borderWidth

uiview - iOS 应用程序 UI 的层次结构