Променете само един конкретен цвят на нюанса на UITabBarItem

Добре известно е, че цветът на нюанса на избрани (или активни) елементи в UITabBarController може лесно да се променя, ето един пример:

myBarController.tabBar.tintColor = [UIColor redColor];

В този случай всеки елемент от лентата с раздели в лентата с раздели ще има червен нюанс, след като стане активен. Отново, това се отнася за всички елементи в тази лента с раздели.

Как цветът на активния нюанс може да се различава между другите елементи на лентата с раздели в същата лента? Например, един елемент може да има червен нюанс, докато е избран, докато друг може да има син нюанс.

Наясно съм, че това вероятно може да бъде решено чрез преначертаване и подкласиране на цялата лента с раздели. Това обаче е единствената промяна, от която се нуждая, и ми се струва прекалено много. Не се опитвам да променя стила или начина, по който елементите се изобразяват по никакъв начин, само за да направя този стил различен между различните елементи.

Не съм виждал никъде отговори на този въпрос, които да са свързани с актуализациите в iOS 7 и 8.


person element119    schedule 23.07.2014    source източник
comment
Моля, проверете моя подробен отговор на: stackoverflow.com/questions/43002013/   -  person erickva    schedule 05.12.2017


Отговори (6)


Има много по-лесен начин да направите това! Добавете това към ViewController кой UITabBar елемент трябва да бъде в друг цвят

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

Вмъкнете това в другите ViewControllers

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

Използвам това, за да получа различни цветове Tint във всеки ViewController, напр.: [red | черно | зелен | розово]

person Kai Burghardt    schedule 13.08.2014
comment
За всеки, който използва swift: tabBarController?.tabBar.tintColor = UIColor.redColor() - person Andrej; 11.03.2016

@element119 решение, използващо swift (за вас, мързеливи):

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
    }
}

Използвам този код, за да оцветя средната си икона в червено:

if let items = self.tabBar.items as? [UITabBarItem] {
    let button = items[1]
    button.image = button.image?.tabBarImageWithCustomTint(UIColor.redColor())
}
person Binsh    schedule 20.08.2015
comment
SWIFT 2: CGBlendMode.Normal вместо kCGBlendModeNormal, Благодаря за горния отговор - person Yogesh Lolusare; 20.11.2015

Направих някои експерименти и въз основа на този отговор намерих начин да правя това, което искам без подклас UITabBarItem или UITabBar!

По принцип идеята е да се създаде метод на UIImage, който имитира поведението на маската за оцветяване на UITabBar, като същевременно го изобразява в „оригиналната“ му форма и избягва естествената маска за оцветяване.

Всичко, което трябва да направите, е да създадете нов метод на екземпляр на UIImage, който връща изображение, маскирано с цвета, който искаме:

@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

Това е сравнително ясна версия на кода в отговора, който публикувах, с едно изключение - върнатото изображение има режим на изобразяване, зададен на винаги оригинален, което гарантира, че маската по подразбиране UITabBar няма да бъде приложена. Сега всичко, което е необходимо, е да използвате този метод, когато редактирате елемент от лентата с раздели:

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

Излишно е да казвам, че selected_image е нормалното изображение, което човек получава от UIImage imageNamed:, а [UIColor redColor може да бъде заменено с всеки цвят, който желаете.

person element119    schedule 23.07.2014

Това работи добре за мен!! код за 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
    }
}

и след...

 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))

Благодаря ;))

person David Torguet    schedule 05.11.2016

swift xcode7.1 тестван:

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
    }
}

поправи грешката за съвместимост в @Binsh отговор

person ergunkocak    schedule 13.11.2015

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
        
    }
    
}
person joel.d    schedule 16.11.2020