假设你有一张图片如下:
在不同的场景下你需要将这个图标显示成不同的颜色,特别是对于有皮肤功能的app来说,这种场景相对多一些。效果如下:
该如何实现呢?本文提供三种实现方法。如果各位看官有更好的实现方法,欢迎留言讨论。
SampleCode on Github
方法一:利用tintColor和renderingMode
UIImage中有一个属性renderingMode,其中一个可能的取值为:UIImageRenderingModeAlwaysTemplate。官方文档中指出:
UIImageRenderingModeAlwaysTemplate
Always draw the image as a template image, ignoring its color information.
通俗地讲,当UIImage的renderingMode为UIImageRenderingModeAlwaysTemplate时,渲染时不再按照原始图片中的颜色进行渲染,颜色的取值统一取view中tintColor。利用这个特性,则就可以实现我们想要的效果啦,代码如下。
1 2 3 4 5 6 7 8 9 10
| - (UIImageView *)imageViewWithSourceImage:(UIImage *)image tintColor:(UIColor *)color { image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; CGRect frame = (CGRect){CGPointZero, image.size};; UIImageView *imageView = [[[UIImageView alloc] initWithFrame:frame] autorelease]; imageView.tintColor = color; imageView.image = image;
return imageView; }
|
方法二:利用layer.mask
CALayer有一个属性mask。对于每一个像素点的alpha值,可以用这个公式计算得出:
1
| content.alpha = originContent.alpha * mask.alpha;
|
利用mask和设置backgroundColor为我们想要的颜色,同样也可以实现。
1 2 3 4 5 6 7 8 9 10 11 12
| - (UIImageView *)imageViewWithSourceImage:(UIImage *)image layerColor:(UIColor *)color { CGRect frame = (CGRect){CGPointZero, image.size};; UIImageView *imageView = [[[UIImageView alloc] initWithFrame:frame] autorelease]; CALayer *layer = [CALayer layer]; layer.frame = imageView.bounds; layer.contents = (id)image.CGImage; imageView.layer.mask = layer; imageView.backgroundColor = color;
return imageView; }
|
这里需要注意的是,不要忘记设置mask的frame。
方法三:CoreGraphics绘制
主要利用CGContextClipToMask方法,将填充区域限制在mask的范围内,再填充颜色即可。
需要注意的是,CG的坐标系和UIKit的坐标系是不同的。UIKit以左上角为原点;CG以左下角为原点,y轴向上。绘制的时候需要注意坐标轴变换。
其次,要注意image的scale处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| - (UIImageView *)imageViewWithSourceImage:(UIImage *)image fillColor:(UIColor *)color { CGRect rect = (CGRect){CGPointZero, image.size};
UIGraphicsBeginImageContextWithOptions(rect.size, NO, image.scale); CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, rect.size.height); CGContextScaleCTM(context, 1.f, -1.f);
CGContextClipToMask(context, rect, image.CGImage);
CGContextSetFillColorWithColor(context, color.CGColor); CGContextFillRect(context, rect);
UIImage *sourceImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();
UIImageView *imageView = [[[UIImageView alloc] initWithFrame:rect] autorelease]; imageView.image = sourceImage;
return imageView; }
|