Change only one specific UITabBarItem tint color

前端 未结 6 2147
猫巷女王i
猫巷女王i 2021-01-05 00:53

It is well known that the tint color of selected (or active) items in a UITabBarController can be easily changed, here is an example:

myBarController.tabBar.         


        
相关标签:
6条回答
  • 2021-01-05 01:15

    @element119 solution using swift(for you lazy guys):

    extension UIImage {
        func tabBarImageWithCustomTint(tintColor: UIColor) -> UIImage {
            UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
            let context: CGContextRef = UIGraphicsGetCurrentContext()
    
            CGContextTranslateCTM(context, 0, self.size.height)
            CGContextScaleCTM(context, 1.0, -1.0)
            CGContextSetBlendMode(context, kCGBlendModeNormal)
            let rect: CGRect = CGRectMake(0, 0, self.size.width, self.size.height)
    
            CGContextClipToMask(context, rect, self.CGImage)
    
            tintColor.setFill()
            CGContextFillRect(context, rect)
    
            var newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
    
            newImage = newImage.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
            return newImage
        }
    }
    

    I'm using this code to tint my middle icon red:

    if let items = self.tabBar.items as? [UITabBarItem] {
        let button = items[1]
        button.image = button.image?.tabBarImageWithCustomTint(UIColor.redColor())
    }
    
    0 讨论(0)
  • 2021-01-05 01:18

    swift xcode7.1 tested :

    extension UIImage {
        func tabBarImageWithCustomTint(tintColor: UIColor) -> UIImage {
            UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
            let context: CGContextRef = UIGraphicsGetCurrentContext()!
    
            CGContextTranslateCTM(context, 0, self.size.height)
            CGContextScaleCTM(context, 1.0, -1.0)
            CGContextSetBlendMode(context, CGBlendMode.Normal)
            let rect: CGRect = CGRectMake(0, 0, self.size.width, self.size.height)
    
            CGContextClipToMask(context, rect, self.CGImage)
    
            tintColor.setFill()
            CGContextFillRect(context, rect)
    
            var newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
    
            newImage = newImage.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
            return newImage
        }
    }
    

    fixed the compatibility bug in @Binsh answer

    0 讨论(0)
  • 2021-01-05 01:23

    I did some experimenting and based on this answer, found a way to do what I want without subclassing UITabBarItem or UITabBar!

    Basically, the idea is to create a method of UIImage that mimics the tint mask behavior of UITabBar, while rendering it in its "original" form and avoiding the native tint mask.

    All you have to do is create a new instance method of UIImage that returns an image masked with the color we want:

    @interface UIImage(Overlay)
    - (instancetype)tabBarImageWithCustomTint:(UIColor *)tintColor;
    @end
    
    @implementation UIImage(Overlay)
    
    - (instancetype)tabBarImageWithCustomTint:(UIColor *)tintColor
    {
        UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextTranslateCTM(context, 0, self.size.height);
        CGContextScaleCTM(context, 1.0, -1.0);
        CGContextSetBlendMode(context, kCGBlendModeNormal);
        CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
        CGContextClipToMask(context, rect, self.CGImage);
        [tintColor setFill];
        CGContextFillRect(context, rect);
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        newImage = [newImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
        return newImage;
    }
    @end
    

    This is a fairly straightforward version of the code in the answer that I posted, with one exception- the returned image has its rendering mode set to always original, which makes sure that the default UITabBar mask won't be applied. Now, all that is needed is to use this method when editing the tab bar item:

    navController.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"title" image:normal_image selectedImage:[selected_image tabBarImageWithCustomTint:[UIColor redColor]]];
    

    Needless to say, selected_image is the normal image one gets from UIImage imageNamed: and the [UIColor redColor can be replaced with any color one desires.

    0 讨论(0)
  • 2021-01-05 01:27

    This worked fine for me!! code for Swift 3

    extension UIImage {
        func tabBarImageWithCustomTint(tintColor: UIColor) -> UIImage {
            UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale)
            let context: CGContext = UIGraphicsGetCurrentContext()!
            context.translateBy(x: 0, y: self.size.height)
            context.scaleBy(x: 1.0, y: -1.0)
            context.setBlendMode(CGBlendMode(rawValue: 1)!)
            let rect: CGRect = CGRect(x: 0, y: 0, width:  self.size.width, height: self.size.height)
            context.clip(to: rect, mask: self.cgImage!)
            tintColor.setFill()
            context.fill(rect)
            var newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
            UIGraphicsEndImageContext()
            newImage = newImage.withRenderingMode(UIImageRenderingMode.alwaysOriginal)
            return newImage
        }
    }
    

    and after...

     button.image = button.image?.tabBarImageWithCustomTint(tintColor: UIColor(red: 30.0/255.0, green: 33.0/255.0, blue: 108.0/255.0, alpha: 1.0))
    

    thanks ;))

    0 讨论(0)
  • 2021-01-05 01:31

    There is a much easier way to do this! Add this to the ViewController which UITabBar Item should be in another color

    - (void) viewWillAppear:(BOOL)animated {
       // change tint color to red
       [self.tabBarController.tabBar setTintColor:[UIColor redColor]];
       [super viewWillAppear: animated];
    }
    

    Insert this to the other ViewControllers

    - (void) viewWillAppear:(BOOL)animated {
       // change tint color to black
       [self.tabBarController.tabBar setTintColor:[UIColor blackColor]];
       [super viewWillAppear: animated];
    }
    

    I use this to get different Tint colors in each ViewController e.g.: [ red | black | green | pink ]

    0 讨论(0)
  • 2021-01-05 01:35

    Swift 5:

    extension UIImage {
        func tintWithColor(color: UIColor) -> UIImage? {
            UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
            guard let context = UIGraphicsGetCurrentContext() else { return nil }
            
            context.scaleBy(x: 1.0, y: -1.0)
            context.translateBy(x: 0.0, y: -self.size.height)
            context.setBlendMode(.multiply)
            
            let rect = CGRect(origin: .zero, size: size)
            guard let cgImage = self.cgImage else { return nil }
            context.clip(to: rect, mask: cgImage)
            color.setFill()
            context.fill(rect)
            
            let newImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            
            return newImage
            
        }
        
    }
    
    0 讨论(0)
提交回复
热议问题