Thay đổi màu sắc của png trong các nút - iOS


93

Tôi có một tập hợp các biểu tượng mà tôi đã tạo là các PNG màu trắng trong suốt:

nhập mô tả hình ảnh ở đây

Và những gì tôi muốn làm là có thể nhuộm chúng thành các màu khác. Chẳng hạn như xanh lam, xám, v.v.

Tôi nhận thấy rằng 'đã nhấp / đã nhấn' chúng tự động thay đổi thành màu xám. Vì vậy, tôi cho rằng tôi có thể thay đổi màu xám đó thành bất kỳ thứ gì tôi thích bằng một lần nhấn hoặc trạng thái bình thường của nó:

nhập mô tả hình ảnh ở đây

Cách tốt nhất để đạt được điều này là gì?

Câu trả lời:


225

Mã sau sẽ thiết lập màu sắc cho trạng thái bình thường của nút:

Đối với Swift 4 và mới hơn:

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

Bạn có thể thay đổi màu sắc theo nhu cầu của bạn khi trạng thái thay đổi cho nút.


Các phiên bản cũ hơn

Đối với Swift 3:

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

Đối với Swift 2: xem lịch sử sửa đổi.


Tuyệt vời! Nhưng làm thế nào để bạn hoàn nguyên về hình ảnh ban đầu (chưa được nhuộm màu)?
Marsman

@Marsman nếu bạn nhìn vào giải pháp gốc của tôi Hình ảnh đại diện cho hình ảnh gốc và màu sắc Hình ảnh đại diện cho phiên bản màu của hình ảnh gốc, vì vậy bạn không thay thế Hình ảnh gốc mà tạo phiên bản mới của nó và bạn sẽ có hai phiên bản của cùng một hình ảnh mà bạn có thể sử dụng làm mỗi nhu cầu của bạn
Yuvrajsinh

không hoạt động trong iOS 11 với xcode 9.1. Khi Thêm màu sắc, nó hoàn toàn thay đổi màu sắc của imageView.
Vineesh TP

Các chỉnh sửa khác nhau đã đưa ra những điểm không chính xác trong câu trả lời này.
Eric Aya

13

iOS 7 đã giới thiệu một thuộc tính gọi là tintColor cho các chế độ xem (bao gồm cả UIImageView). Tuy nhiên, bạn cũng cần đặt kiểu kết xuất trên UIImage để điều này có hiệu lực.

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];

Điều này sẽ tạo ra hiệu ứng như bạn đang ở trạng thái mặc định.


10

Bạn có thể sử dụng tiện ích mở rộng này:

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
Điều này cũng không hiệu quả với tôi. Khi tôi sử dụng phương pháp này, tất cả những gì tôi thấy là màu sắc chứ không phải hình ảnh được nhuộm màu đó.
Moebius

9

Để thay đổi màu sắc của hình ảnh ( chọn , hình ảnh cổ điển , hình ảnh ), hãy sử dụng:

Hình ảnh ví dụ: nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Swift 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

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

}

u có thể cho tôi biết làm thế nào để sử dụng các phương pháp này có nghĩa là làm thế nào để gọi chúng?
ashmi123

Điều này không hiệu quả đối với tôi. Tôi có một PNG được đặt làm hình ảnh của nút. Khi tôi sử dụng tintPhoto hoặc tintPicto, chúng không hoạt động.
Moebius

Bạn có thêm hình ảnh của mình vớiRenderingMode (.alwaysTemplate) không? @Moebius
YannSteph

Có, và khi tôi sử dụng một trong hai phương pháp tint, tất cả những gì tôi thấy là màu sắc. Tôi thậm chí đã đặt alpha của màu thành 0,5 và tôi vẫn chỉ thấy màu. Swift 4
Moebius

Ok áp dụng alpha sau khi pha màu @Moebius
YannSteph

8

Nếu bạn đang thiết lập hình ảnh cho một nút, chỉ cần đi tới trình kiểm tra thuộc tính và thay đổi loại nút thành hệ thống. Sau đó thiết lập hình ảnh và thay đổi màu sắc. Màu sắc của hình ảnh sẽ thay đổi. Nếu nó không diễn ra, hãy kiểm tra loại nút.


7

Swift 4 hoặc 5

extension UIButton{

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

}

Sử dụng:

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

không có bất kỳ phương pháp nào của setImageTintColor cho chế độ xem UIbutton
Wahab Khan Jadon

Nó là một phần mở rộng của UIButton. Tôi đã tạo ở trên.
Krunal Patel

6

Nếu sử dụng danh mục nội dung, bạn có thể đặt nội dung hình ảnh hiển thị ở chế độ mẫu. Sau đó, bạn có thể đặt màu của nút trong Trình tạo giao diện (hoặc trong mã) và nó sẽ mất.


Đây là cách tốt nhất nếu bạn đang sử dụng cùng một hình ảnh ở nhiều nơi vì bạn chỉ đặt hình ảnh ở chế độ mẫu một lần trong Danh mục nội dung.
Jonathan Cabrera

Cách tiếp cận này không hiệu quả với tôi. Khi tôi đặt PNG làm hình ảnh mẫu và sau đó đặt màu sắc, hình ảnh sẽ được thay thế bằng màu sắc.
Moebius

Đây cũng là cách tiếp cận tốt nhất cho tôi. Cảm ơn rất nhiều. Đơn giản dễ dàng tái sử dụng ...
Alparslan Selçuk Develioğlu

4

Swift 4

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

3

Nếu sử dụng danh mục nội dung, bạn có thể đặt nội dung hình ảnh hiển thị ở chế độ mẫu. Sau đó, bạn có thể đặt màu sắc của nút trong Trình tạo giao diện (hoặc trong mã) và nó sẽ mất.


1

Tôi đã tìm thấy cách tiếp cận dễ nhất bên dưới,

Mở danh mục tài sản và chọn hình ảnh, sau đó chuyển đến trình kiểm tra thuộc tính và thay đổi Render Asthành Template Imagenhư bên dưới

nhập mô tả hình ảnh ở đây

Sau đó thêm mã bên dưới vào nút Phương pháp hành động

yourButton.tintColor = .gray

-1

Swift 4 và 4.2

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

nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.