I noticed that when I place a white or black UIImage into a UISegmentedControl it automatically color masks it to match the tint of the segmented control. I thought this was really cool, and was wondering if I could do this elsewhere as well. For example, I have a bunch of buttons that have a uniform shape but varied colors. Instead of making a PNG for each button, could I somehow use this color masking to use the same image for all of them but then set a tint color or something to change their actual color?


当前回答

从ios7开始,在UIImage上有一个新的方法来指定渲染模式。使用渲染模式UIImageRenderingModeAlwaysTemplate将允许图像颜色由按钮的色调颜色控制。

objective - c

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *image = [[UIImage imageNamed:@"image_name"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[button setImage:image forState:UIControlStateNormal]; 
button.tintColor = [UIColor redColor];

斯威夫特

let button = UIButton(type: .custom)
let image = UIImage(named: "image_name")?.withRenderingMode(.alwaysTemplate)
button.setImage(image, for: .normal)
button.tintColor = UIColor.red

其他回答

如果你想手动屏蔽你的图像,这里是更新的代码,适用于视网膜屏幕

- (UIImage *)maskWithColor:(UIColor *)color
{
    CGImageRef maskImage = self.CGImage;
    CGFloat width = self.size.width * self.scale;
    CGFloat height = self.size.height * self.scale;
    CGRect bounds = CGRectMake(0,0,width,height);

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef bitmapContext = CGBitmapContextCreate(NULL, width, height, 8, 0, colorSpace, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast);
    CGContextClipToMask(bitmapContext, bounds, maskImage);
    CGContextSetFillColorWithColor(bitmapContext, color.CGColor);
    CGContextFillRect(bitmapContext, bounds);

    CGImageRef cImage = CGBitmapContextCreateImage(bitmapContext);
    UIImage *coloredImage = [UIImage imageWithCGImage:cImage scale:self.scale orientation:self.imageOrientation];

    CGContextRelease(bitmapContext);
    CGColorSpaceRelease(colorSpace);
    CGImageRelease(cImage);

    return coloredImage;
}

如果你在ios15之后到达这里,你使用的是新的UIButton。配置api,那么您可能需要通过imageColorTransformer来实现。

看起来是这样的:

configuration.imageColorTransformer = UIConfigurationColorTransformer { _ in .green }

为了方便,你可以创建一个扩展:

extension UIButton.Configuration {
    func imageColor(_ color: UIColor) -> UIButton.Configuration {
        var configuration = self
        configuration.imageColorTransformer = UIConfigurationColorTransformer { _ in color }
        return configuration
    }
}

// Usage:
configuration = configuration.imageColor(.green)

与其他答案一样,图像本身必须在Xcode资产中“渲染为模板图像”,或者在code image. withrenderingmode (.alwaysTemplate)中


小贴士: 如果您想在按钮高亮显示时改变图像颜色,该怎么办?然后你的配置扩展看起来像这样:

func imageColor(whenNormal: UIColor,
                whenHighlighted: UIColor,
                isHighlighted: Bool) -> UIButton.Configuration {
    var configuration = self
    configuration.imageColorTransformer = UIConfigurationColorTransformer { _ in
        isHighlighted ? whenHighlighted : whenNormal
    }
    return configuration
}

这个本身必须从configurationUpdateHandler上下文中调用,就像这样:

someButton.configurationUpdateHandler = { button in
    guard var configuration = button.configuration else {  return }
    configuration.image = UIImage(named: "some_image")
    configuration = configuration.imageColor(whenNormal: .green,
                                             whenHighlighted: .green.withAlphaComponent(0.7),
                                             isHighlighted: button.isHighlighted)
    button.configuration = configuration
}

注意,您还可以在configurationUpdateHandler中根据按钮状态定义不同的映像。

为了在按钮上设置白色的图像(箭头图标),我们使用:

let imageOnButton = UIImage(named: "navForwardArrow")?.imageWithColor(color: UIColor.white)
button.setImage(imageOnButton, for: .normal)

已知问题:当按下按钮时,图标会失去白色。

截图:

从ios7开始,在UIImage上有一个新的方法来指定渲染模式。使用渲染模式UIImageRenderingModeAlwaysTemplate将允许图像颜色由按钮的色调颜色控制。

objective - c

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *image = [[UIImage imageNamed:@"image_name"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[button setImage:image forState:UIControlStateNormal]; 
button.tintColor = [UIColor redColor];

斯威夫特

let button = UIButton(type: .custom)
let image = UIImage(named: "image_name")?.withRenderingMode(.alwaysTemplate)
button.setImage(image, for: .normal)
button.tintColor = UIColor.red

改变按钮图像或图像视图色调颜色

btn.imageView?.image = btn.imageView?.image?.withRenderingMode(.alwaysTemplate)

btn.imageView?.tintColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)