防止UITabBar将渐变应用于其图标图像

当我为UITabBar制作图标时,它会对图像应用渐变。 我需要知道如何防止这个渐变。

苹果在iOS 5中添加了标签栏定制,现在这种东西是微不足道的。 在此之前,这是一个巨大的黑客,并不推荐。

以下是如何做一个完全自定义的标签栏:

// custom icons UITabBarItem *item = [[UITabBarItem alloc] init]; item.title = @"foo"; // setting custom images prevents the OS from applying a tint color [item setFinishedSelectedImage:[UIImage imageNamed:@"tab1_active.png"] withFinishedUnselectedImage:[UIImage imageNamed:@"tab1_image_deselected.png"]]; tab1ViewController.tabBarItem = item; // tab bar // set background image - will be used instead of glossy black tabBarController.tabBar.backgroundImage = [UIImage imageNamed:@"tab_bar_bg.png"]; // optionally set the tint color - setting this ti nil will result in the standard, blue tint color. tint color is ignored when custom icons are set as above. tabBarController.tabBar.selectedImageTintColor = nil; // remove the highlight around the selected tab - or provide an alternate highlight image. If you don't do this the iOS default is to draw a highlighted box beneath the selected tab icon. tabBarController.tabBar.selectionIndicatorImage = [[UIImage alloc] init]; 

这是非常困难的,因为UITabBar不提供对select/未select图像的访问。 它可以通过私有API来实现:

 @interface UITabBar (ColorExtensions) - (void)recolorItemsWithColor:(UIColor *)color shadowColor:(UIColor *)shadowColor shadowOffset:(CGSize)shadowOffset shadowBlur:(CGFloat)shadowBlur; @end @interface UITabBarItem (Private) @property(retain, nonatomic) UIImage *selectedImage; - (void)_updateView; @end @implementation UITabBar (ColorExtensions) - (void)recolorItemsWithColor:(UIColor *)color shadowColor:(UIColor *)shadowColor shadowOffset:(CGSize)shadowOffset shadowBlur:(CGFloat)shadowBlur { CGColorRef cgColor = [color CGColor]; CGColorRef cgShadowColor = [shadowColor CGColor]; for (UITabBarItem *item in [self items]) if ([item respondsToSelector:@selector(selectedImage)] && [item respondsToSelector:@selector(setSelectedImage:)] && [item respondsToSelector:@selector(_updateView)]) { CGRect contextRect; contextRect.origin.x = 0.0f; contextRect.origin.y = 0.0f; contextRect.size = [[item selectedImage] size]; // Retrieve source image and begin image context UIImage *itemImage = [item image]; CGSize itemImageSize = [itemImage size]; CGPoint itemImagePosition; itemImagePosition.x = ceilf((contextRect.size.width - itemImageSize.width) / 2); itemImagePosition.y = ceilf((contextRect.size.height - itemImageSize.height) / 2); UIGraphicsBeginImageContext(contextRect.size); CGContextRef c = UIGraphicsGetCurrentContext(); // Setup shadow CGContextSetShadowWithColor(c, shadowOffset, shadowBlur, cgShadowColor); // Setup transparency layer and clip to mask CGContextBeginTransparencyLayer(c, NULL); CGContextScaleCTM(c, 1.0, -1.0); CGContextClipToMask(c, CGRectMake(itemImagePosition.x, -itemImagePosition.y, itemImageSize.width, -itemImageSize.height), [itemImage CGImage]); // Fill and end the transparency layer CGContextSetFillColorWithColor(c, cgColor); contextRect.size.height = -contextRect.size.height; CGContextFillRect(c, contextRect); CGContextEndTransparencyLayer(c); // Set selected image and end context [item setSelectedImage:UIGraphicsGetImageFromCurrentImageContext()]; UIGraphicsEndImageContext(); // Update the view [item _updateView]; } } @end 

人们甚至可以创造一些非常酷的效果:

红色选项卡栏uploads/RedTabBar.png

苹果很可能会拒绝这样做的申请。 如果未来的操作系统更新中删除私有API,
-[UITabBar recolorItemsWithColor:shadowColor:shadowOffset:shadowBlur:]将不会做任何事情,而不是崩溃。

添加渐变非常简单,请添加以下几行代码:

CGFloat components[8] = {0.0,0.4,1.0,0.2,0.0,0.6,1.0,1.0}; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGGradientRef colorGradient = CGGradientCreateWithColorComponents(colorSpace, components, NULL, 2); CGContextDrawLinearGradient(cxt, colorGradient,CGPointZero,CGPointMake(0,contextRect.size.height),0);
CGFloat components[8] = {0.0,0.4,1.0,0.2,0.0,0.6,1.0,1.0}; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGGradientRef colorGradient = CGGradientCreateWithColorComponents(colorSpace, components, NULL, 2); CGContextDrawLinearGradient(cxt, colorGradient,CGPointZero,CGPointMake(0,contextRect.size.height),0); 

这会让你非常接近苹果在tabbar上做的事情,但不是确切的。 为了达到目的,只需在组件中添加两个点/颜色,而不是在CGGradientCreateWithColorComponents中使用NULL ,请使用类似于{0,0.5,0.6,1.0} 。 实际上,所有你需要的是一个背景色和三个alpha点(颜色部分都是1,因为你只需要阴影,同时保留一个单一的颜色configuration文件)。

我会发布我的代码,如果这不清楚…干杯。

已经差不多一年了,但是这里是代码。 将这个作为一个类别添加到UIImage或转换为类的范围。 请记住,您传递的图像(自我)必须是仅包含alpha的图像(蒙版是基于图像的可见部分创build的)。

 - (UIImage *) imageWithBackgroundColor:(UIColor *)bgColor shadeAlpha1:(CGFloat)alpha1 shadeAlpha2:(CGFloat)alpha2 shadeAlpha3:(CGFloat)alpha3 shadowColor:(UIColor *)shadowColor shadowOffset:(CGSize)shadowOffset shadowBlur:(CGFloat)shadowBlur { UIImage *image = self; CGColorRef cgColor = [bgColor CGColor]; CGColorRef cgShadowColor = [shadowColor CGColor]; CGFloat components[16] = {1,1,1,alpha1,1,1,1,alpha1,1,1,1,alpha2,1,1,1,alpha3}; CGFloat locations[4] = {0,0.5,0.6,1}; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGGradientRef colorGradient = CGGradientCreateWithColorComponents(colorSpace, components, locations, (size_t)4); CGRect contextRect; contextRect.origin.x = 0.0f; contextRect.origin.y = 0.0f; contextRect.size = [image size]; //contextRect.size = CGSizeMake([image size].width+5,[image size].height+5); // Retrieve source image and begin image context UIImage *itemImage = image; CGSize itemImageSize = [itemImage size]; CGPoint itemImagePosition; itemImagePosition.x = ceilf((contextRect.size.width - itemImageSize.width) / 2); itemImagePosition.y = ceilf((contextRect.size.height - itemImageSize.height) / 2); UIGraphicsBeginImageContext(contextRect.size); CGContextRef c = UIGraphicsGetCurrentContext(); // Setup shadow CGContextSetShadowWithColor(c, shadowOffset, shadowBlur, cgShadowColor); // Setup transparency layer and clip to mask CGContextBeginTransparencyLayer(c, NULL); CGContextScaleCTM(c, 1.0, -1.0); CGContextClipToMask(c, CGRectMake(itemImagePosition.x, -itemImagePosition.y, itemImageSize.width, -itemImageSize.height), [itemImage CGImage]); // Fill and end the transparency layer CGContextSetFillColorWithColor(c, cgColor); contextRect.size.height = -contextRect.size.height; CGContextFillRect(c, contextRect); CGContextDrawLinearGradient(c, colorGradient,CGPointZero,CGPointMake(contextRect.size.width*1.0/4.0,contextRect.size.height),0); CGContextEndTransparencyLayer(c); //CGPointMake(contextRect.size.width*3.0/4.0, 0) // Set selected image and end context UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); CGColorSpaceRelease(colorSpace); CGGradientRelease(colorGradient); return resultImage; } 

例如,以下内容会产生一个非常类似于本机标签栏的效果:

 UIImage *niceImage = [[UIImage imageNamed:@"image_name"] imageWithBackgroundColor:[UIColor colorWithRed:41.0/255.0 green:147.0/255.0 blue:239.0/255.0 alpha:1.0] shadeAlpha1:0.6 shadeAlpha2:0.0 shadeAlpha3:0.4 shadowColor:[UIColor blackColor] shadowOffset:CGSizeMake(0.0f, -1.0f) shadowBlur:3.0]; 

有一个解决scheme,使用iDev食谱网站上的自定义实施标签栏。

http://idevrecipes.com/2011/01/04/how-does-the-twitter-iphone-app-implement-a-custom-tab-bar

使用下面的图片(假设,tabBar有5个标签如下)

  • 在这里输入图像描述
  • 在这里输入图像描述
  • 在这里输入图像描述
  • 在这里输入图像描述
  • 在这里输入图像描述

使用“TabBar应用程序”模板创build一个新项目并放置以下代码。

AppDel.h文件的内容。

 #import <UIKit/UIKit.h> @interface cTabBarAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> { } @property (nonatomic, retain) IBOutlet UIWindow *window; @property (nonatomic, retain) IBOutlet UITabBarController *tabBarController; @property (nonatomic, retain) IBOutlet UIImageView *imgV; @end 

AppDel.m文件的内容。

 #import "cTabBarAppDelegate.h" @implementation cTabBarAppDelegate @synthesize window=_window; @synthesize tabBarController=_tabBarController; @synthesize imgV = _imgV; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.tabBarController.delegate=self; self.imgV.frame=CGRectMake(0, 425, 320, 55); [self.tabBarController.view addSubview:self.imgV]; self.tabBarController.selectedIndex=0; self.window.rootViewController = self.tabBarController; [self.window makeKeyAndVisible]; return YES; } - (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{ NSUInteger index=[[tabBarController viewControllers] indexOfObject:viewController]; switch (index) { case 0: self.imgV.image=[UIImage imageNamed:@"tBar1.png"]; break; case 1: self.imgV.image=[UIImage imageNamed:@"tBar2.png"]; break; case 2: self.imgV.image=[UIImage imageNamed:@"tBar3.png"]; break; case 3: self.imgV.image=[UIImage imageNamed:@"tBar4.png"]; break; case 4: self.imgV.image=[UIImage imageNamed:@"tBar5.png"]; break; default: break; } return YES; } 

我问了一个关于如何为button的“offstate”着色的问题。 有人给我一个解决scheme,也有去除梯度的奖金。 这是问题和他的答案:

问: iphone – tabbar设置imagetintcolor(offstate)

答:请看一下UITabBarItem文档中的“pipe理完成和选定的图像”任务部分。