UILabel 添加 CAGradientLayer 处理流程图
一、包含中文的文本,为何可以实现 CAGradientLayer 作为背景如图所示,如果 UILabel 的文本是中文,系统会添加一个 _UILabelContentLayer,将本文绘制在此层。并且会插入到 UILabel.layer.sublayers 的第一位。
UILabel 添加 CAGradientLayer 处理流程图
![](https://img.haomeiwen.com/i6526232/bb7ce0802a911f20.png)
一、包含中文的文本,为何可以实现 CAGradientLayer 作为背景
![](https://img.haomeiwen.com/i6526232/97e0624279661952.png)
如图所示,如果 UILabel 的文本是中文,系统会添加一个 _UILabelContentLayer,将本文绘制在此层。并且会插入到 UILabel.layer.sublayers 的第一位。
![](https://img.haomeiwen.com/i6526232/b4f7ce5911682208.png)
这个时候,如果我们把 CAGradientLayer.zPosition 设置为负值,默认的 CALayer.zPosition = 0, 在渲染的时候,就会先渲染渐变层,然后渲染文本层。这就可以实现用一个渐变色作为背景的目的。
二、不包含中文的文本,为何不可以实现 CAGradientLayer 作为背景
![](https://img.haomeiwen.com/i6526232/6f43af03a638f862.png)
如果文本不包含中文,系统会把文本绘制在 UILabel.layer (_UILabelLayer) 层。此层是 CAGradientLayer 的父 layer,无论如何,都会先于 CAGradientLayer 层渲染。因此 CAGradientLayer 层渲染后,会遮盖文本,达不到目的。
三、iOS 14+,包含中文的文本,为何又不能实现 CAGradientLayer 作为背景
![](https://img.haomeiwen.com/i6526232/a239372706f84426.png)
在 iOS14+,苹果做了优化,即便文本包含中文,也不会添加 _UILabelContentLayer 层,直接绘制在 _UILabelLayer 层。因此,再也不能实现一个 CAGradientLayer 作为背景了。
四、解决方法
只能把 CAGradientLayer 放在 UILabel 的父视图上面,来实现渐变色背景。
五、实验代码
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) UILabel *label;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
self.label = label;
[self.view addSubview:self.label];
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = label.bounds;
gradientLayer.colors = @[(__bridge id)[UIColor redColor].CGColor, (__bridge id)[[UIColor redColor] colorWithAlphaComponent:0.8].CGColor];
gradientLayer.locations = @[@0, @1.0];
gradientLayer.startPoint = CGPointMake(0, 0);
gradientLayer.endPoint = CGPointMake(0, 1);
[label.layer insertSublayer:gradientLayer atIndex:0];
label.text = @"中文aaaaaaa";
// label.text = @"aaaaaaaa";
gradientLayer.zPosition = -10;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSLog(@"%@", self.label.layer);
NSLog(@"%@", self.label.layer.sublayers);
}
@end
网友评论