前言
前段时间工作中,产品给了一个实现渐变色文本,并且是放到富文本里面的需求。插入到富文本这里先不说,无非就是生成这个渐变Label的一张Image插入到富文本。相信大家第一时间可能会去度娘寻求答案,并且马上就能搜索出答案。这里我们来聊聊几种方案的实现,以及产生的问题。
方案一
基于CAGradientLayer做一个mask,核心代码大概如下。
override func layoutSubviews() {
super.layoutSubviews()
guard let config = self.config else { return }
if self.gradientLayer != nil {
return
}
let gradientLayer = CAGradientLayer()
self.gradientLayer = gradientLayer
gradientLayer.colors = [config.startColor.cgColor,config.endColor.cgColor]
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = CGPoint(x: 1, y: 1)
gradientLayer.frame = self.label.frame
gradientLayer.mask = self.label.layer
self.label.layer.frame = gradientLayer.bounds
self.layer.insertSublayer(gradientLayer, at: 0)
}
来看看实现效果:
image看到这里大家是否意味已经大结局了?实际上我一开始确实用此方法直接提交给测试了,结果就翻车了。测试提交了一个如下的Bugs,如果显示了emoj表情,会显示上有bugs如下。
image为什么会有此问题?原理上其实也很简单,CAGradientLayer的方式,实际上是在Label上面盖一层蒙版,如果用了emoj系统可不会给你考虑那么多,翻车倒是正常。所以接下来就要考虑另外一种方式了。
方案二
基于UIColor(patternImage: gradientImage),这个方法,直接给Label设置一张渐变的图片的颜色。(注意这个gradientImage要与你Label的Frame大小是要一致的,不然那个渐变效果不一定会和设计一致。)代码大概如下:
@objc convenience init(config: GradientPatternLabelConfig) {
self.init(frame: .zero)
self.config = config
self.label.font = config.font
self.label.text = config.text
self.addSubview(self.label)
self.label.sizeToFit()
self.label.lineBreakMode = config.lineBreakMode
let size = (config.maxWidth == 0 || self.label.jf.size.width < config.maxWidth) ? self.label.jf.size : CGSize(width: config.maxWidth, height: self.label.jf.size.height)
if config.startColor == UIColor.clear {
self.label.textColor = config.textColor
}
else if let gradientImage = ConvertGradientImage.gradientImage(with: config, size: size) {
self.label.textColor = UIColor(patternImage: gradientImage)
}
else {
self.label.textColor = config.startColor
}
let frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
self.label.frame = frame
self.frame = frame
}
生成gradientImage的代码:
+ (UIImage *_Nullable)gradientImageWithConfig:(GradientPatternLabelConfig *_Nonnull)config size:(CGSize)size {
UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);
CGContextRef context = UIGraphicsGetCurrentContext();
//绘制渐变层
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradientRef = CGGradientCreateWithColors(colorSpaceRef,
(__bridge CFArrayRef)@[(id)config.startColor.CGColor,(id)config.endColor.CGColor],
NULL);
CGPoint startPoint = CGPointZero;
CGRect rect = CGRectMake(0, 0, size.width, size.height);
CGPoint endPoint = CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect));
CGContextDrawLinearGradient(context, gradientRef, startPoint, endPoint, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
//取到渐变图片
UIImage *gradientImage = UIGraphicsGetImageFromCurrentImageContext();
//释放资源
CGColorSpaceRelease(colorSpaceRef);
CGGradientRelease(gradientRef);
UIGraphicsEndImageContext();
return gradientImage;
}
接下来就是见证奇迹的时候:
image
网友评论