ボタンの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は元のイメージのティントバージョンを表すため、元のイメージを置き換えるのではなく、新しいバージョンを作成し、同じイメージの2つのバージョンを使用できます。必要に応じて
Yuvrajsinh 2016

xcode 9.1のiOS 11では動作しません。濃淡色を追加すると、imageViewの色が完全に変わります。
Vineesh TP

さまざまな編集により、この回答に不正確さが生じています。
エリックアヤ

13

iOS 7では、ビュー(UIImageViewを含む)にtintColorというプロパティが導入されました。ただし、これが効果を発揮するには、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 2017年

これは私にはまったく機能しません。ボタンの画像としてPNGを設定しています。tintPhotoまたはtintPictoを使用すると、機能しません。
メビウス

あなたはあなたの画像をRenderingMode(.alwaysTemplate)で追加しますか?@メビウス
YannSteph

はい、そして私がいずれかのティント方法を使用するとき、私が見るすべては色です。色のアルファを0.5に設定しても、色だけが表示されます。スウィフト4
メビウス

ティントの後にアルファを適用します@メビウス
YannSteph

8

ボタンの画像を設定する場合は、属性インスペクターに移動して、ボタンタイプをシステムに変更します。次に、画像を設定し、色合いの色を変更します。画像の色が変わります。実行されなかった場合は、ボタンのタイプを確認してください。


7

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

UIbuttonビューにはsetImageTintColorのメソッドはありません
Wahab Khan Jadon

UIButtonの拡張です。上記で作成しました。
Krunal Patel

6

アセットカタログを使用する場合、テンプレートモードでレンダリングするように画像アセット自体を設定できます。その後、インターフェイスビルダー(またはコード)でボタンのtintColorを設定できます。


アセットカタログで画像を一度テンプレートモードに設定するだけなので、同じ画像を複数の場所で使用する場合は、これが最良の方法です。
ジョナサンカブレラ

このアプローチは私にはうまくいきませんでした。PNGをテンプレート画像として設定してから濃淡色を設定すると、画像が濃淡色に置き換えられます。
メビウス

これは私にとっても最善のアプローチです。どうもありがとう。シンプルで簡単に再利用可能...
AlparslanSelçukDevelioğlu

4

スウィフト4

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

3

アセットカタログを使用する場合、テンプレートモードでレンダリングするように画像アセット自体を設定できます。その後、Interface Builder(またはコード)でボタンのtintColorを設定できます。


1

私は以下の最も簡単なアプローチを見つけました、

assetcatalogを開いて画像を選択し、属性インスペクタに移動Render AsTemplate Imageて以下のように変更します

ここに画像の説明を入力してください

次に、ボタンのアクションメソッドに以下のコードを追加します

yourButton.tintColor = .gray

-1

Swift 4および4.2

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

ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.