![](https://img.haomeiwen.com/i3402387/d7c6514d82aacfad.png)
我们先来一个简单的卡拉OK效果练练手吧
![](https://img.haomeiwen.com/i3402387/3d0f375f233ccf62.gif)
这个非常容易,设置定时器计算进度progress。重写UILabel的drawRect:
,通过progress计算颜色区域,然后填充颜色就行,不过要注意一下填充方式。
// 这里计算字体大小与frame需要做一些优化。因为该方式调用非常多
- (void)setProgress:(CGFloat)progress{
_progress = progress;
if (_progress == 0) {
[self setFont:[UIFont systemFontOfSize:14]];
} else {
[self setFont:[UIFont boldSystemFontOfSize:16]];
}
[self sizeToFit];
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
CGFloat width = self.frame.size.width * self.progress;
CGRect colorRect = CGRectMake(0, 0, width, self.frame.size.height);
if (self.color) {
[self.color setFill];
} else {
[[UIColor redColor] setFill];
}
UIRectFill(fillRect);
}
目前得到的效果是一下形式的:
![](https://img.haomeiwen.com/i3402387/6eb0cdf34f184a69.gif)
因为填充方式不对,这里需要使用另一个函数UIRectFillUsingBlendMode
:
// UIRectFill(fillRect);
UIRectFillUsingBlendMode(colorRect, kCGBlendModeSourceIn);
现在了解到填充方式有两种:直接所有覆盖和有内容显示的位置覆盖。通过UIRectFillUsingBlendMode
还可以设置很多种填充方式。
再来一个比较漂亮的UISearchBar
![](https://img.haomeiwen.com/i3402387/4dc106bfcd693705.png)
![](https://img.haomeiwen.com/i3402387/3a061ae8343b84aa.png)
也是比较简单,直接上代码了:
// 初始化方法中用到。initWithCoder:、initWithFrame:
- (void)setup {
// 设置背景图是为了去掉上下黑线
self.backgroundImage = [[UIImage alloc] init];
// 设置SearchBar的颜色主题为白色
self.barTintColor = [UIColor whiteColor];
// 修正光标颜色
self.tintColor = [UIColor colorWithRGB:Color_Green_V];
// 设置搜索Icon
[self setImage:[UIImage imageNamed:@"Search_Icon"] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];
}
- (void)layoutSubviews {
[super layoutSubviews];
// 设置圆角和边框颜色
UITextField *searchField = [self valueForKey:@"searchField"];
if (searchField) {
[searchField setBackgroundColor:[UIColor whiteColor]];
searchField.font = [UIFont systemFontOfSize:Font_Normal];
searchField.layer.cornerRadius = searchField.height * 0.5;
searchField.layer.borderColor = [UIColor colorWithRGB:Color_Green_V].CGColor;
searchField.layer.borderWidth = 1;
searchField.layer.masksToBounds = YES;
}
}
现在我们开始实现一下今天的目标效果
![](https://img.haomeiwen.com/i3402387/d7c6514d82aacfad.png)
在此之前要用到渐变效果
![](https://img.haomeiwen.com/i3402387/5d7c4a55fd6d6758.png)
UIView *backView = [UIView new];
backView.frame = CGRectMake(0, -20, ScreenW, 64);
CAGradientLayer *gradientLayer = [[CAGradientLayer alloc] init];
gradientLayer.frame = CGRectMake(0, 0, ScreenW, 64);
gradientLayer.colors = @[(__bridge id)[UIColor colorWithHex:0xe8292a alpha:0.76].CGColor,(__bridge id)[UIColor colorWithHex:0x60d653 alpha:0.28].CGColor];
gradientLayer.startPoint = CGPointMake(0, 0);
gradientLayer.endPoint = CGPointMake(0, 1.0);
[backView.layer addSublayer:gradientLayer];
虽然知道要用到渐变,但是怎么实现目标效果中指定路径还有文字的颜色渐变呢?
1、创建一个label,并设置layer.cornerRadius
、layer.borderColor
与layer.borderWidth
。
2、大家应该都知道CALayer中有个mask属性,并且他也是一个CALayer对象。那么我们是否可以通过上边的label的layer设置成一个layer的mask呢?而渐变图层CAGradientLayer继承自CALayer,当然也有mask属性,如果它的mask赋值为label.layer是不是能实现我们想要的效果了?开始行动,试一哈
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(30, 130, 250, 50)];
view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:view];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 200, 30)];
label.text = @"哈哈哈哈哈哈哈哈";
label.textAlignment = NSTextAlignmentCenter;
// label.textColor = [UIColor clearColor];
label.layer.cornerRadius = 15;
label.layer.borderColor = [UIColor blackColor].CGColor;
label.layer.borderWidth = 1;
[view addSubview:label];
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = label.frame;
gradientLayer.colors = @[(__bridge id)[UIColor colorWithHex:0xe8292a alpha:0.76].CGColor,(__bridge id)[UIColor colorWithHex:0x60d653 alpha:0.28].CGColor];
gradientLayer.startPoint = CGPointMake(0, 0);
gradientLayer.endPoint = CGPointMake(1.0, 1.0);
[view.layer addSublayer:gradientLayer];
gradientLayer.mask = label.layer;
// 父层改了,坐标系需要重新设置
label.frame = gradientLayer.bounds;
呵呵,很高兴就这么完成了。
上边代码需要注意和了解的是:
1,mask图层,根据透明度进行裁剪,只保留非透明部分,显示底部内容。所以label的文字颜色与边框颜色不能为空。
2,因为label的layer设置为别的图层的mask时,frame机制改变了,所以坐标系需要重新设置。
另外可能还想让这个渐变的颜色一直变化,还可以加一个定时器。
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.5 repeats:YES block:^(NSTimer * _Nonnull timer) {
gradientLayer.colors = @[(__bridge id)[UIColor randomColor].CGColor, (__bridge id)[UIColor randomColor].CGColor,(__bridge id)[UIColor randomColor].CGColor];
}];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
![](https://img.haomeiwen.com/i3402387/f3ada3b8169432e0.gif)
现在我们将上边的label,换成button,希望点击文字时有响应。代码就不写了,结果是没有任何响应。Debug view hierarchy之后,发现button控件是不存在的。回到以前的代码,发现label也同样是不存在的。
注意:一旦把控件层设置为mask层,控件层就不能显示了,会直接从父层中移除,然后作为渐变层的mask层,且控件层的父层会指向渐变层。
那么怎么让其有点击事件呢?将上边代码的父控件view的类型改为UIButton即可。😂😂😂
网友评论