如何iOS更改UIBarButtonItem的文本颜色

在iOS平台,UINavigationBar可以通过设置tintColor来改变导航条的背景颜色,但是由于UIBarButtonItem没有文本颜色设置功能,所以如果将UINavigationBar的tintColor设置成whiteColor的话,文字显示就不怎么清晰了。如下图:

这种情况网上一般建议通过建立一个UILabel,赋值给UINavigationItem的titleView属性,改变标题的颜色。建立一个UIButton,通过UIBarButtonItem的

initWithCustomView方法创建UIBarButtonItem对象,得到结果如下图:

效果不尽人意吧。当然可以通过设置背景图片什么的,加强效果。但总体来说不如只改变文本颜色方便。

iOS的Objective C提供了runtime函数,定义在objc目录下面。通过这些运行时库函数可以对系统定义的对象进行修改,比如增加方法,修改方法的代码地址....通过枚举UINavigationBar的子视图,发现显示UIBarButtonItem内容的是UINavigationButton,它有一个子视图类型为UIButtonLabel,UIButtonLabel继承自UILabel,UIButtonLabel类型本身没有重载setTextColor:方法,因此调用class_addMethod给UIButtonLabel类型增加一个setTextColor:方法,然后把传进来的color强制改成其他颜色,再调用UILabel的setTextColor:方法即可。

void ChangeUINavigationButtonTextColor() {
    // 给UIButtonLabel增加setTextColor:方法
    Class class = objc_getClass("UIButtonLabel");
    Method m = class_getInstanceMethod([UILabel class], @selector(setTextColor:));
    class_addMethod(class, @selector(setTextColor:), (IMP)UIButtonLabelSetTextColor, method_getTypeEncoding(m));
    // 修改阴影颜色
    m = class_getInstanceMethod([UILabel class], @selector(UIButtonLabelSetShadowColor:));
    class_addMethod(class, @selector(setShadowColor:), (IMP)UIButtonLabelSetTextColor, method_getTypeEncoding(m));
}

void UIButtonLabelSetTextColor(id self, SEL _cmd, UIColor *textColor) {
    // 改变UIBarButtonItem的文字颜色
    if ([[self superview] isKindOfClass:objc_getClass("UINavigationButton")]) {
        // 因为UIButtonLabel在其他地方也用到了,比如UIAlertView中的按钮,因此这里判断一下,确定是导航条按钮的时候才更改颜色
        textColor = [UIColor blackColor];
    }
    struct objc_super super = {self, [UILabel class]};
    objc_msgSendSuper(&super, @selector(setTextColor:), textColor);
}


void UIButtonLabelSetShadowColor(id self, SEL _cmd, UIColor *shadowColor) {
    if ([[self superview] isKindOfClass:objc_getClass("UINavigationButton")]) {
        shadowColor = [UIColor whiteColor];
    }
    struct objc_super super = {self, [UILabel class]};
    objc_msgSendSuper(&super, @selector(setShadowColor:), shadowColor);
}

ChangeUINavigationButtonTextColor是修改UIButtonLabel类型,增加setTextColor:方法,

UIButtonLabelSetTextColor是改变颜色的具体实现。

UIApplicationDelegate的实现类型中的- (BOOL)application:didFinishLaunchingWithOptions:方法中调用ChangeUINavigationButtonTextColor函数。

@implementation AppDelegate_iPhone

@synthesize window;


#pragma mark -
#pragma mark Application lifecycle

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    
    // Override point for customization after application launch.
    ChangeUINavigationButtonTextColor();
    
	UINavigationController *navigationController = [[[UINavigationController alloc] initWithRootViewController:[MainFrame makeNewController]] autorelease];
	navigationController.delegate = self;
	navigationController.navigationBar.barStyle = UIBarStyleDefault;
	navigationController.navigationBar.tintColor = [UIColor whiteColor];
	navigationController.toolbar.tintColor = [UIColor whiteColor];
	self.window.rootViewController = navigationController;
	
	[self.window makeKeyAndVisible];
    
    return YES;
}
@end

上图为效果,不过还没有完全完成,因为返回按钮和标题的颜色还没有改变


实现方法类似,返回按钮和标题的视图类型是UINavigationItemButtonView,他的父类UINavigationItemView有一个专门用来画文字的函数-(void)drawText:inRect:barStyle:,这个方法在不同的固件版本上可能不一样,在3.x版本可能是-(void)drawText:inRect:这种形式,这个没什么影响,要覆盖低版本的话无非是多写两个函数。下面是完整的实现代码

void ChangeUINavigationButtonTextColor() {
    Class class = objc_getClass("UIButtonLabel");
    Method m = class_getInstanceMethod([UILabel class], @selector(setTextColor:));
    class_addMethod(class, @selector(setTextColor:), (IMP)UIButtonLabelSetTextColor, method_getTypeEncoding(m));
    
    m = class_getInstanceMethod([UILabel class], @selector(setShadowColor:));
    class_addMethod(class, @selector(setShadowColor:), (IMP)UIButtonLabelSetShadowColor, method_getTypeEncoding(m));
    
    class = objc_getClass("UINavigationItemView");
    m = class_getInstanceMethod(class, @selector(drawText:inRect:barStyle:));
    method_setImplementation(m, (IMP)UINavigationItemViewDrawText);
}

void UIButtonLabelSetTextColor(id self, SEL _cmd, UIColor *textColor) {
    if ([[self superview] isKindOfClass:objc_getClass("UINavigationButton")]) {
        textColor = [UIColor blackColor];
    }
    struct objc_super super = {self, [UILabel class]};
    objc_msgSendSuper(&super, @selector(setTextColor:), textColor);
}

void UIButtonLabelSetShadowColor(id self, SEL _cmd, UIColor *shadowColor) {
    if ([[self superview] isKindOfClass:objc_getClass("UINavigationButton")]) {
        shadowColor = [UIColor whiteColor];
    }
    struct objc_super super = {self, [UILabel class]};
    objc_msgSendSuper(&super, @selector(setShadowColor:), shadowColor);
}

void UINavigationItemViewDrawText(id self, SEL _cmd, NSString *text, struct CGRect rect, UIBarStyle barStyle) {
    UIFont *f = [self font];
    if (!f) {
        f = objc_msgSend(self, @selector(_defaultFont));
    }
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(ctx, [UIColor blackColor].CGColor);
    [text drawInRect:rect withFont:f lineBreakMode:UILineBreakModeTailTruncation alignment:UITextAlignmentCenter];
    CGContextAddRect(ctx, rect);
}
最后的问题是这些代码能不能通过AppStore的审查,这个我暂时也不知道,感觉应该是可行的,毕竟runtime不算私有API吧。最后上个整图














  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值