Змінити колір png на кнопках - ios


93

У мене є набір значків, які я створив, які є прозорими білими PNG:

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

І що я хотів би зробити, це мати можливість тонувати їх в інші кольори. Такі як синій, сірий тощо.

Я помітив, що "клацання / натискання" вони автоматично змінюються на сірий. Тому я припускаю, що я можу змінити цей сірий на будь-який, що мені подобається, або краном, або його нормальним станом:

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

Який найкращий спосіб досягти цього?

Відповіді:


225

Наступний код встановить колір відтінку для нормального стану кнопки:

Для Swift 4 та новіших версій:

let origImage = UIImage(named: "imageName")
let tintedImage = origImage?.withRenderingMode(.alwaysTemplate)
btn.setImage(tintedImage, for: .normal)
btn.tintColor = .red

Ви можете змінити колір відтінку відповідно до ваших потреб, коли стан кнопки змінюється.


Старіші версії

Для Swift 3:

let origImage = UIImage(named: "imageName")
let tintedImage = origImage?.withRenderingMode(.alwaysTemplate)
btn.setImage(tintedImage, forState: .normal)
btn.tintColor = .redColor

Для Swift 2: див. Історію редагувань.


Чудово! Але як повернутися до початкового зображення (нефарбованого)?
Marsman

@Marsman, якщо ви подивитесь на моє рішення originaImage представляє оригінальне зображення, а tintedImage представляє тоновану версію оригінального зображення, тому ви не замінюєте оригінальне зображення, а створюєте нову його версію, і у вас буде дві версії одного зображення, які ви можете використовувати як за вашими потребами
Ювраджсін

не працює в iOS 11 з xcode 9.1. Коли додається колір відтінку, він повністю змінює колір imageView.
Vineesh TP

Різні редагування внесли неточності у цю відповідь.
Eric Aya

13

iOS 7 представив властивість під назвою tintColor для переглядів (включаючи UIImageView). Однак вам також потрібно встановити тип візуалізації на UIImage, щоб це мало якийсь ефект.

UIImage *originalImage = [UIImage imageNamed:@"image.png"];
UIImage *tintedImage = [originalImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
UIImageView *imageView = [[UIImageView alloc] initWithImage:tintedImage];

imageView.tintColor = [UIColor grayColor];
[self.view addSubview:imageView];

Це має дати ефект, який ви шукаєте в стані за замовчуванням.


10

Ви можете використовувати це розширення:

import UIKit

extension CGContext {

    func fill(_ rect: CGRect,
              with mask: CGImage,
              using color: CGColor) {

        saveGState()
        defer { restoreGState() }

        translateBy(x: 0.0, y: rect.size.height)
        scaleBy(x: 1.0, y: -1.0)
        setBlendMode(.normal)

        clip(to: rect, mask: mask)

        setFillColor(color)
        fill(rect)
    }
}

extension UIImage {

    func filled(with color: UIColor) -> UIImage {
        let rect = CGRect(origin: .zero, size: self.size)
        guard let mask = self.cgImage else { return self }

        if #available(iOS 10.0, *) {
            let rendererFormat = UIGraphicsImageRendererFormat()
            rendererFormat.scale = self.scale

            let renderer = UIGraphicsImageRenderer(size: rect.size,
                                                   format: rendererFormat)
            return renderer.image { context in
                context.cgContext.fill(rect,
                                       with: mask,
                                       using: color.cgColor)
            }
        } else {
            UIGraphicsBeginImageContextWithOptions(rect.size,
                                                   false,
                                                   self.scale)
            defer { UIGraphicsEndImageContext() }

            guard let context = UIGraphicsGetCurrentContext() else { return self }

            context.fill(rect,
                         with: mask,
                         using: color.cgColor)
            return UIGraphicsGetImageFromCurrentImageContext() ?? self
        }
    }
}

1
Це теж не працює у мене. Коли я використовую цей метод, я бачу лише колір, а не зображення, що підфарбовує цей колір.
Мебіус

9

Для зміни відтінку зображення ( підбір , класичне зображення , фото ) використовуйте таке:

Приклад зображення: введіть тут опис зображення введіть тут опис зображення

Стрімкий 2

public extension UIImage {
    /**
     Tint, Colorize image with given tint color<br><br>
     This is similar to Photoshop's "Color" layer blend mode<br><br>
     This is perfect for non-greyscale source images, and images that have both highlights and shadows that should be preserved<br><br>
     white will stay white and black will stay black as the lightness of the image is preserved<br><br>

     <img src="http://yannickstephan.com/easyhelper/tint1.png" height="70" width="120"/>

     **To**

     <img src="http://yannickstephan.com/easyhelper/tint2.png" height="70" width="120"/>

     - parameter tintColor: UIColor

     - returns: UIImage
     */
    public func tintPhoto(tintColor: UIColor) -> UIImage {

        return modifiedImage { context, rect in
            // draw black background - workaround to preserve color of partially transparent pixels
            CGContextSetBlendMode(context, .Normal)
            UIColor.blackColor().setFill()
            CGContextFillRect(context, rect)

            // draw original image
            CGContextSetBlendMode(context, .Normal)
            CGContextDrawImage(context, rect, self.CGImage)

            // tint image (loosing alpha) - the luminosity of the original image is preserved
            CGContextSetBlendMode(context, .Color)
            tintColor.setFill()
            CGContextFillRect(context, rect)

            // mask by alpha values of original image
            CGContextSetBlendMode(context, .DestinationIn)
            CGContextDrawImage(context, rect, self.CGImage)
        }
    }
    /**
     Tint Picto to color

     - parameter fillColor: UIColor

     - returns: UIImage
     */
    public func tintPicto(fillColor: UIColor) -> UIImage {

        return modifiedImage { context, rect in
            // draw tint color
            CGContextSetBlendMode(context, .Normal)
            fillColor.setFill()
            CGContextFillRect(context, rect)

            // mask by alpha values of original image
            CGContextSetBlendMode(context, .DestinationIn)
            CGContextDrawImage(context, rect, self.CGImage)
        }
    }
    /**
     Modified Image Context, apply modification on image

     - parameter draw: (CGContext, CGRect) -> ())

     - returns: UIImage
     */
    private func modifiedImage(@noescape draw: (CGContext, CGRect) -> ()) -> UIImage {

        // using scale correctly preserves retina images
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        let context: CGContext! = UIGraphicsGetCurrentContext()
        assert(context != nil)

        // correctly rotate image
        CGContextTranslateCTM(context, 0, size.height);
        CGContextScaleCTM(context, 1.0, -1.0);

        let rect = CGRectMake(0.0, 0.0, size.width, size.height)

        draw(context, rect)

        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

UPD

Стрімкий 3

extension UIImage {

    /**
     Tint, Colorize image with given tint color<br><br>
     This is similar to Photoshop's "Color" layer blend mode<br><br>
     This is perfect for non-greyscale source images, and images that have both highlights and shadows that should be preserved<br><br>
     white will stay white and black will stay black as the lightness of the image is preserved<br><br>

     <img src="http://yannickstephan.com/easyhelper/tint1.png" height="70" width="120"/>

     **To**

     <img src="http://yannickstephan.com/easyhelper/tint2.png" height="70" width="120"/>

     - parameter tintColor: UIColor

     - returns: UIImage
     */
    func tintPhoto(_ tintColor: UIColor) -> UIImage {

        return modifiedImage { context, rect in
            // draw black background - workaround to preserve color of partially transparent pixels
            context.setBlendMode(.normal)
            UIColor.black.setFill()
            context.fill(rect)

            // draw original image
            context.setBlendMode(.normal)
            context.draw(cgImage!, in: rect)

            // tint image (loosing alpha) - the luminosity of the original image is preserved
            context.setBlendMode(.color)
            tintColor.setFill()
            context.fill(rect)

            // mask by alpha values of original image
            context.setBlendMode(.destinationIn)
            context.draw(context.makeImage()!, in: rect)
        }
    }

    /**
     Tint Picto to color

     - parameter fillColor: UIColor

     - returns: UIImage
     */
    func tintPicto(_ fillColor: UIColor) -> UIImage {

        return modifiedImage { context, rect in
            // draw tint color
            context.setBlendMode(.normal)
            fillColor.setFill()
            context.fill(rect)

            // mask by alpha values of original image
            context.setBlendMode(.destinationIn)
            context.draw(cgImage!, in: rect)
        }
    }

    /**
     Modified Image Context, apply modification on image

     - parameter draw: (CGContext, CGRect) -> ())

     - returns: UIImage
     */
    fileprivate func modifiedImage(_ draw: (CGContext, CGRect) -> ()) -> UIImage {

        // using scale correctly preserves retina images
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        let context: CGContext! = UIGraphicsGetCurrentContext()
        assert(context != nil)

        // correctly rotate image
        context.translateBy(x: 0, y: size.height)
        context.scaleBy(x: 1.0, y: -1.0)

        let rect = CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height)

        draw(context, rect)

        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image!
    }

}

можеш сказати мені, як використовувати ці методи, означає, як їх викликати?
ashmi123

Для мене це взагалі не працює. У мене зображення PNG встановлено як зображення кнопки. Коли я використовую або tintPhoto, або tintPicto, вони просто не працюють.
Мебіус

Ви додаєте своє зображення за допомогою RenderingMode (.alwaysTemplate)? @Meebius
YannSteph

Так, і коли я використовую будь-який із методів відтінку, я бачу лише колір. Я навіть встановив альфа-колір на 0,5, і я все ще бачу лише колір. Swift 4
Мебіус

Гаразд застосовувати альфу після відтінку @Meebius
YannSteph

8

Якщо ви встановлюєте зображення для кнопки, просто перейдіть до інспектора атрибутів і змініть тип кнопки на системний. Потім встановіть зображення та змініть колір відтінку. Зміниться колір зображення. Якщо це не відбулося, перевірте тип кнопки.


7

Свіфт 4 або 5

extension UIButton{

    func setImageTintColor(_ color: UIColor) {
        let tintedImage = self.imageView?.image?.withRenderingMode(.alwaysTemplate)
        self.setImage(tintedImage, for: .normal)
        self.tintColor = color
    }

}

Використання:

button.setImage(UIImage(named: "image_name"), for: .normal) // You can set image direct from Storyboard
button.setImageTintColor(UIColor.white)

немає жодного методу setImageTintColor для перегляду UIbutton
Wahab Khan

Це продовження UIButton. Я створив вище.
Крунал Патель,

6

Якщо ви використовуєте каталоги об’єктів, ви можете встановити, що сам об’єкт зображення відображатиметься в режимі шаблону. Після цього ви можете встановити tintColor кнопки в Interface Builder (або в коді), і він повинен прийняти.


Це найкращий підхід, якщо ви використовуєте одне і те ж зображення у кількох місцях, оскільки лише один раз встановили зображення в режим шаблону в Каталозі активів.
Джонатан Кабрера,

Цей підхід для мене не спрацював. Коли я встановлюю PNG як шаблонне зображення, а потім встановлюю колір відтінку, зображення замінюється кольором відтінку.
Мебіус

Це найкращий підхід і для мене. Дуже дякую. Простий легкий багаторазовий ...
Альпарслан Сельчук Девеліоглу,

4

Стрімкий 4

    let origImage = UIImage(named: "check")
    let tintedImage = origImage?.withRenderingMode(.alwaysTemplate)
    buttons[0].setImage(tintedImage, for: .normal)
    buttons[0].tintColor = .red

3

Якщо ви використовуєте каталоги об’єктів, ви можете встановити, що сам об’єкт зображення відображатиметься в режимі шаблону. Після цього ви можете встановити tintColor кнопки в Interface Builder (або в коді), і він повинен прийняти.


1

Я знайшов найпростіший підхід нижче,

Відкрийте каталог активів і виберіть зображення, а потім перейдіть до інспектора атрибутів і змініть Render Asна, Template Imageяк показано нижче

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

Потім додайте код нижче в кнопку Дія методу

yourButton.tintColor = .gray

-1

Свіфт 4 і 4.2

let img = UIImage.init(named: "buttonName")?.withRenderingMode(UIImageRenderingMode.alwaysTemplate)
            btn.setImage(img, for: .normal)
            btn.tintColor = .gray

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.