버튼의 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

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

2
이것은 나에게도 작동하지 않습니다. 이 방법을 사용할 때 내가 보는 모든 것은 그 색을 칠한 이미지가 아니라 색입니다.
Moebius

9

이미지의 색조 변경 ( pick , classic image , photo ) 다음을 사용하십시오.

예시 이미지 : 여기에 이미지 설명 입력 여기에 이미지 설명 입력

스위프트 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 2019

좋아, 색조 @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)

있는 UIButton 뷰 setImageTintColor 어떤 메소드는 없다
와하 칸 정호

UIButton의 확장입니다. 위에서 만들었습니다.
Krunal Patel

6

자산 카탈로그를 사용하는 경우 이미지 자산 자체를 템플릿 모드에서 렌더링하도록 설정할 수 있습니다. 그런 다음 Interface Builder (또는 코드)에서 버튼의 tintColor를 설정할 수 있으며 가져와야합니다.


자산 카탈로그에서 이미지를 템플릿 모드로 한 번만 설정하므로 여러 위치에서 동일한 이미지를 사용하는 경우 가장 좋은 방법입니다.
Jonathan Cabrera

이 접근 방식은 저에게 효과적이지 않았습니다. PNG를 템플릿 이미지로 설정 한 다음 색조 색상을 설정하면 이미지가 색조 색상으로 대체됩니다.
Moebius

이것은 나에게도 가장 좋은 방법입니다. 감사합니다. 간단하고 쉽게 재사용 할 수 있습니다 ...
Alparslan Selçuk Develioğ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를 설정할 수 있으며 가져와야합니다.


3

아래에서 가장 쉬운 방법을 찾았습니다.

열기 assetcatalog 및 이미지를 선택한 후 이동 속성 관리자 및 변경 Render AsTemplate Image아래와 같이

여기에 이미지 설명 입력

그런 다음 버튼 Action 메서드에 아래 코드를 추가하십시오.

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.