เปลี่ยนสีของ png ในปุ่ม - iOS


95

ฉันมีชุดไอคอนที่ฉันสร้างขึ้นซึ่งเป็น PNG สีขาวโปร่งใส:

ป้อนคำอธิบายภาพที่นี่

และสิ่งที่ฉันอยากทำคือสามารถย้อมสีให้เป็นสีอื่นได้ เช่นสีฟ้าสีเทาเป็นต้น

ฉันสังเกตเห็นว่า "คลิก / แตะ" จะเปลี่ยนเป็นสีเทาโดยอัตโนมัติ ดังนั้นฉันถือว่าฉันสามารถเปลี่ยนสีเทานั้นเป็นอะไรก็ได้ที่ฉันชอบด้วยการแตะหรือสถานะปกติ:

ป้อนคำอธิบายภาพที่นี่

อะไรคือวิธีที่ดีที่สุดในการบรรลุเป้าหมายนี้?

คำตอบ:


231

รหัสต่อไปนี้จะตั้งค่าสีอ่อนสำหรับสถานะปกติของปุ่ม:

สำหรับ 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 แสดงถึงภาพต้นฉบับที่มีสีอ่อนดังนั้นคุณจึงไม่ได้แทนที่ภาพต้นฉบับ แต่สร้างเวอร์ชันใหม่และคุณจะมีภาพเดียวกันสองเวอร์ชันที่คุณสามารถใช้เป็น ตามความต้องการของคุณ
Yuvrajsinh

ไม่ทำงานใน iOS 11 ที่มี xcode 9.1 เมื่อ Add the tint color จะเป็นการเปลี่ยนสีของ 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
        }
    }
}

2
สิ่งนี้ใช้ไม่ได้กับฉันเช่นกัน เมื่อฉันใช้วิธีนี้สิ่งที่ฉันเห็นคือสีไม่ใช่ภาพที่ย้อมสีนั้น
Moebius

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 ก็ไม่ได้ผล
Moebius

คุณเพิ่มรูปภาพของคุณด้วยRenderingMode (.alwaysTemplate) หรือไม่ @Moebius
YannSteph

ใช่และเมื่อฉันใช้วิธีการย้อมสีอย่างใดอย่างหนึ่งสิ่งที่ฉันเห็นคือสี ฉันยังตั้งค่าอัลฟาของสีเป็น 0.5 และฉันก็ยังเห็นแค่สี Swift 4
Moebius

โอเคทาอัลฟ่าหลังแต้มสี @Moebius
YannSteph

9

หากคุณกำลังตั้งค่ารูปภาพสำหรับปุ่มเพียงไปที่ตัวตรวจสอบแอตทริบิวต์และเปลี่ยนประเภทปุ่มเป็นระบบ จากนั้นตั้งค่าภาพและเปลี่ยนสีอ่อน สีของภาพจะเปลี่ยนไป หากไม่เกิดขึ้นให้ตรวจสอบประเภทปุ่ม


9

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)

ไม่มีวิธีใด ๆ ของ setImageTintColor สำหรับมุมมอง UIbutton
Wahab Khan Jadon

มันเป็นส่วนขยายของ UIButton ฉันได้สร้างไว้ด้านบน
Krunal Patel

6

หากคุณใช้แค็ตตาล็อกเนื้อหาคุณสามารถตั้งค่าเนื้อหารูปภาพเพื่อแสดงผลในโหมดเทมเพลต หลังจากนั้นคุณสามารถตั้งค่า tintColor ของปุ่มใน Interface Builder (หรือในรหัส) และควรใช้


นี่เป็นแนวทางที่ดีที่สุดหากคุณใช้รูปภาพเดียวกันในหลาย ๆ ที่เนื่องจากคุณตั้งค่ารูปภาพเป็นโหมดเทมเพลตเพียงครั้งเดียวในแคตตาล็อกเนื้อหา
Jonathan Cabrera

วิธีนี้ไม่ได้ผลสำหรับฉัน เมื่อฉันตั้ง PNG เป็นรูปภาพเทมเพลตแล้วตั้งค่าสีอ่อนรูปภาพจะถูกแทนที่ด้วยสีอ่อน
Moebius

นี่เป็นแนวทางที่ดีที่สุดสำหรับฉันด้วย ขอบคุณมาก. ง่ายต่อการใช้ซ้ำ ...
Alparslan Selç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

หากคุณใช้แค็ตตาล็อกเนื้อหาคุณสามารถตั้งค่าเนื้อหารูปภาพเพื่อแสดงผลในโหมดเทมเพลต หลังจากนั้นคุณสามารถตั้งค่า tintColor ของปุ่มใน Interface Builder (หรือในรหัส) และควรใช้


3

ฉันพบวิธีที่ง่ายที่สุดด้านล่าง

เปิด assetcatalog และเลือกภาพจากนั้นไปที่คุณลักษณะการตรวจสอบและการเปลี่ยนแปลงRender AsไปTemplate Imageดังต่อไปนี้

ป้อนคำอธิบายภาพที่นี่

จากนั้นเพิ่มโค้ดด้านล่างในปุ่มวิธีการดำเนินการ

yourButton.tintColor = .gray

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.