Color Tint UIButton Image

294

Я заметил , что когда я устанавливаю белый или черные UIImageв UISegmentedControlнем автоматически цветов масок , чтобы соответствовать цветовому тону сегментированного управления. Я думал, что это действительно круто, и мне было интересно, смогу ли я сделать это в другом месте. Например, у меня есть несколько кнопок, которые имеют одинаковую форму, но разные цвета. Вместо того, чтобы делать PNG для каждой кнопки, могу ли я как-то использовать эту цветовую маскировку, чтобы использовать одно и то же изображение для всех них, но затем установить цвет оттенка или что-то, чтобы изменить их фактический цвет?

Логан Шир
источник
Можете ли вы опубликовать изображение, которое вы хотите использовать, а также изображение для желаемого результата?
Пратюша Терли
то же самое можно сделать из конструктора интерфейсов stackoverflow.com/a/25179217/2051381
Chuy47

Ответы:

619

Начиная с iOS 7, есть новый метод UIImageдля указания режима рендеринга. Использование режима рендеринга UIImageRenderingModeAlwaysTemplateпозволит цвету изображения управлять цветом оттенка кнопки.

Objective-C

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *image = [[UIImage imageNamed:@"image_name"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[button setImage:image forState:UIControlStateNormal]; 
button.tintColor = [UIColor redColor];

стриж

let button = UIButton(type: .custom)
let image = UIImage(named: "image_name")?.withRenderingMode(.alwaysTemplate)
button.setImage(image, for: .normal)
button.tintColor = UIColor.red
Рик Сантос
источник
14
Я думаю, что лучше использовать button.imageView.tintColor
M.Othman
3
@ M. Отман работает только для меня, когда я использую button.tintColor, а не button.imageview.tintColor
pnizzle
32
Только не забудьте установить режим рендеринга изображения на изображении в xcassets per @hashier
Дин
23
Создание UIButton типа UIButtonTypeSystem автоматически выполнит заданный вами tintColor.
Carloshwa
4
Если у вас tintColorслишком темно, убедитесь, что adjustsImageWhenHighlightedнет. (Или в IB: «Выделенное изображение настраивается» не отмечено.)
Джейсон Мур
225

Как уже упоминал Рик в своем посте, вы можете установить режим рендеринга в коде, вы также можете сделать это прямо в каталоге изображений, см. Прикрепленное изображение ниже. Просто установите Render AsнаTemplate Image

введите описание изображения здесь

Будьте у меня проблемы с iOS 7 и таким подходом. Так что, если вы используете iOS 7 также, вы можете сделать это в коде, чтобы быть уверенным, как описано здесь .

hashier
источник
1
В качестве примечания, файл изображения должен быть черным и прозрачным (не ч / б)
Аксель Гильмин
6
@AxelGuilmin не совсем. Ваше изображение может быть любого цвета и прозрачным. Любой цвет, отличный от прозрачного, будет преобразован в общий, а затем по умолчанию будет окрашен в черный цвет.
Алехандро Иван
90

Пользовательские кнопки отображаются в соответствующих цветах изображения. Если для кнопки установить тип «Система» в раскадровке (или UIButtonTypeSystemв коде), изображение кнопки будет отображаться с оттенком цвета по умолчанию.

Система типов кнопок отображает тонированные значки

(протестировано на iOS9, Xcode 7.3)

Auco
источник
2
Чего можно избежать с помощью методов alwaysTemplate и tintColor, предложенных здесь. С преимуществом кнопки .system вы можете изменить цвет, нажав на кран.
Крис Принс
44

Вы должны установить режим рендеринга изображений UIImageRenderingModeAlwaysTemplate, чтобы иметь возможность tintColorвлиять на UIImage. Вот решение в Swift:

let image = UIImage(named: "image-name")
let button = UIButton()
button.setImage(image?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate), forState: .Normal)
button.tintColor = UIColor.whiteColor()

SWIFT 4x

button.setImage(image.withRenderingMode(UIImage.RenderingMode.alwaysTemplate), for: .normal)
button.tintColor = UIColor.blue
Ник Варнье
источник
28

Если у вас есть пользовательская кнопка с фоновым изображением. Вы можете установить цвет оттенка вашей кнопки и переопределить изображение следующим.

В активах выберите фон кнопки, которую вы хотите установить оттенок цвета.

В инспекторе атрибутов изображения установите значение render как «Шаблон изображения»

введите описание изображения здесь

Теперь, когда вы установите button.tintColor = UIColor.redкнопку, она будет отображаться красным цветом.

Илкер Балтачи
источник
если вы здесь, вы можете перейти по этой ссылке: useyourloaf.com/blog/styling-buttons-using-the-asset-catalog и перейти к шаблонным изображениям (в качестве объяснения)
cspam
Это лучшее решение, так как оно сокращает код и делает то же самое, что и принятый ответ.
DS.
Я думаю, что это должно быть правильным. меньше кода и прост в обращении.
Umair_UAS
17

В Swift вы можете сделать это так:

var exampleImage = UIImage(named: "ExampleImage.png")?.imageWithRenderingMode(.AlwaysTemplate)

Тогда по вашему мнению DidLoad

exampleButtonOutlet.setImage(exampleImage, forState: UIControlState.Normal)

И чтобы изменить цвет

exampleButtonOutlet.tintColor = UIColor(red: 1, green: 0, blue: 0, alpha: 1) //your color

EDIT Xcode 8 Теперь вы можете просто рендеринга режим изображения в ваших .xcassets для шаблона изображения и тогда вам не нужно специально объявить его в var exampleImageбольше

Хенрик-DMG
источник
14

Не уверен, что именно вы хотите, но этот метод категории будет маскировать UIImage с указанным цветом, чтобы вы могли иметь одно изображение и изменить его цвет на любой другой.

ImageUtils.h

- (UIImage *) maskWithColor:(UIColor *)color;

ImageUtils.m

-(UIImage *) maskWithColor:(UIColor *)color 
{
    CGImageRef maskImage = self.CGImage;
    CGFloat width = self.size.width;
    CGFloat height = self.size.height;
    CGRect bounds = CGRectMake(0,0,width,height);

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef bitmapContext = CGBitmapContextCreate(NULL, width, height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
    CGContextClipToMask(bitmapContext, bounds, maskImage);
    CGContextSetFillColorWithColor(bitmapContext, color.CGColor);    
    CGContextFillRect(bitmapContext, bounds);

    CGImageRef cImage = CGBitmapContextCreateImage(bitmapContext);
    UIImage *coloredImage = [UIImage imageWithCGImage:cImage];

    CGContextRelease(bitmapContext);
    CGColorSpaceRelease(colorSpace);
    CGImageRelease(cImage);

    return coloredImage;    
}

Импортируйте категорию ImageUtils и сделайте что-то вроде этого ...

#import "ImageUtils.h"

...

UIImage *icon = [UIImage imageNamed:ICON_IMAGE];

UIImage *redIcon = [icon maskWithColor:UIColor.redColor];
UIImage *blueIcon = [icon maskWithColor:UIColor.blueColor];
Кирби Тодд
источник
3
Используйте kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLastнаCGBitmapContextCreate
Луис Аскорб
4
Хорошо, но нужно настроить изображение Retina ... Когда я запускаю его на изображении Retina, оно возвращает мне изображение без Retina.
Джоуи
Для поддержки устройств Retina можно использовать масштаб свойство UIDeviceкласса: свойство существует как из прошивки 4.0. CGFloat scale = [UIScreen mainScreen].scale; CGFloat width = self.size.width * scale; CGFloat height = self.size.height * scale;scale
Филипп Фришмут
Вам также нужно использовать scaleзначение при UIImageсоздании:UIImage *coloredImage = [UIImage imageWithCGImage:cImage scale:scale orientation:self.imageOrientation];
Филипп Фришмут
8

Swift 4 с customType:

let button = UIButton(frame: aRectHere)
    let buttonImage = UIImage(named: "imageName")
    button.setImage(buttonImage?.withRenderingMode(.alwaysTemplate), for: .normal)
    button.tintColor = .white
aBikis
источник
5

Для Xamarin.iOS (C #):

        UIButton messagesButton = new UIButton(UIButtonType.Custom);
        UIImage icon = UIImage.FromBundle("Images/icon.png");
        messagesButton.SetImage(icon.ImageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate), UIControlState.Normal);
        messagesButton.TintColor = UIColor.White;
        messagesButton.Frame = new RectangleF(0, 0, 25, 25);
Маца
источник
5

Свифт 3 :

Это решение может быть удобным, если вы уже установили изображение через конструктор интерфейса xCode. В основном у вас есть одно расширение для раскрашивания изображения:

extension UIImage {
    public func image(withTintColor color: 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.normal)
        let rect: CGRect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
        context.clip(to: rect, mask: self.cgImage!)
        color.setFill()
        context.fill(rect)
        let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return newImage
    }
}

Затем вы можете подготовить это расширение UIButton, чтобы раскрасить изображение для определенного состояния:

extension UIButton {
    func imageWith(color:UIColor, for: UIControlState) {
        if let imageForState = self.image(for: state) {
            self.image(for: .normal)?.withRenderingMode(.alwaysTemplate)
            let colorizedImage = imageForState.image(withTintColor: color)
            self.setImage(colorizedImage, for: state)
        }
    }
}

Использование:

myButton.imageWith(.red, for: .normal)

PS (работает хорошо и в ячейках таблицы, вам не нужно вызывать setNeedDisplay()метод, изменение цвета происходит немедленно из-за расширения UIImage ..

Алессандро Орнано
источник
3

Если вы хотите вручную замаскировать свое изображение, вот обновленный код, который работает с экранами сетчатки

- (UIImage *)maskWithColor:(UIColor *)color
{
    CGImageRef maskImage = self.CGImage;
    CGFloat width = self.size.width * self.scale;
    CGFloat height = self.size.height * self.scale;
    CGRect bounds = CGRectMake(0,0,width,height);

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef bitmapContext = CGBitmapContextCreate(NULL, width, height, 8, 0, colorSpace, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast);
    CGContextClipToMask(bitmapContext, bounds, maskImage);
    CGContextSetFillColorWithColor(bitmapContext, color.CGColor);
    CGContextFillRect(bitmapContext, bounds);

    CGImageRef cImage = CGBitmapContextCreateImage(bitmapContext);
    UIImage *coloredImage = [UIImage imageWithCGImage:cImage scale:self.scale orientation:self.imageOrientation];

    CGContextRelease(bitmapContext);
    CGColorSpaceRelease(colorSpace);
    CGImageRelease(cImage);

    return coloredImage;
}
Джош Бернфельд
источник
2

Ты должен попытаться

После настройки кадра

NSArray *arr10 =[NSArray arrayWithObjects:btn1,btn2,nil];
for(UIButton *btn10 in arr10)
{
CAGradientLayer *btnGradient2 = [CAGradientLayer layer];
btnGradient2.frame = btn10.bounds;

btnGradient2.colors = [NSArray arrayWithObjects:
                       (id)[[UIColor colorWithRed:151.0/255.0f green:206.0/255.5 blue:99.0/255.0 alpha:1] CGColor],
                       (id)[[UIColor colorWithRed:126.0/255.0f green:192.0/255.5 blue:65.0/255.0 alpha:1]CGColor],
                       nil];
[btn10.layer insertSublayer:btnGradient2 atIndex:0];

}
guptha
источник
2

Swift 3.0

    let image = UIImage(named:"NoConnection")!

 warningButton = UIButton(type: .system)        
    warningButton.setImage(image, for: .normal)
    warningButton.tintColor = UIColor.lightText
    warningButton.frame = CGRect(origin: CGPoint(x:-100,y:0), size: CGSize(width: 59, height: 56))

    self.addSubview(warningButton)
Джад
источник
1

Изменение цвета изображения кнопки или вида изображения Swift:

btn.imageView?.image = btn.imageView?.image?.withRenderingMode(.alwaysTemplate)

btn.imageView?.tintColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
Урвиш Моди
источник
-1

Ничто из вышеперечисленного не помогло мне, потому что оттенок был очищен после щелчка. Я должен был использовать

button.setImageTintColor(Palette.darkGray(), for: UIControlState())
Шимон Климашевский
источник