iOS自定义PDProgressView:如何将进度条文字白色改为透明
解决进度条文字镂空(透明显示背景)的问题
嘿,我明白你想要的效果——就是进度条上的文字能"镂空",透过文字看到进度条的背景色对吧?之前直接把文字颜色改成clearColor没用,是因为原来的绘制逻辑根本不是为这种镂空效果设计的,咱们换个思路就能搞定。
方案一:用混合模式快速实现(改动最小)
这个方法利用Core Graphics的混合模式,直接在前景色上"挖"出文字形状,透出下面的背景。修改你的drawRect:方法就行:
- (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); CGSize size = self.bounds.size; // 先画整个进度条的背景色 UIColor *backgroundColor = [UIColor greenColor]; [backgroundColor setFill]; CGContextFillRect(context, self.bounds); // 画已完成进度的前景色 UIColor *foregroundColor = [UIColor whiteColor]; [foregroundColor setFill]; CGRect progressRect = CGRectMake(0, 0, self.progress * size.width, size.height); CGContextFillRect(context, progressRect); // 准备文字内容和样式 NSString *progressText = [NSString stringWithFormat:@"%d", (int)round(self.progress * 100)]; UIFont *font = [UIFont boldSystemFontOfSize:42.0]; NSDictionary *textAttrs = @{ NSFontAttributeName: font, // 这里颜色随便设,混合模式会忽略它,只取文字的形状 NSForegroundColorAttributeName: [UIColor blackColor] }; CGSize textSize = [progressText sizeWithAttributes:textAttrs]; CGPoint textPos = CGPointMake(ceil((size.width - textSize.width)/2), ceil((size.height - textSize.height)/2)); // 关键:用kCGBlendModeDestinationOut混合模式画文字,相当于挖空前景色 CGContextSaveGState(context); CGContextSetBlendMode(context, kCGBlendModeDestinationOut); [progressText drawAtPoint:textPos withAttributes:textAttrs]; CGContextRestoreGState(context); }
方案二:用文字做遮罩(更直观的思路)
如果混合模式有点抽象,你可以用文字作为遮罩,让前景色只填充非文字的区域,这样文字区域就自然透出背景了:
- (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); CGSize size = self.bounds.size; // 先画背景色 UIColor *backgroundColor = [UIColor greenColor]; [backgroundColor setFill]; CGContextFillRect(context, self.bounds); // 准备文字内容 NSString *progressText = [NSString stringWithFormat:@"%d", (int)round(self.progress * 100)]; UIFont *font = [UIFont boldSystemFontOfSize:42.0]; NSDictionary *textAttrs = @{NSFontAttributeName: font}; CGSize textSize = [progressText sizeWithAttributes:textAttrs]; CGPoint textPos = CGPointMake(ceil((size.width - textSize.width)/2), ceil((size.height - textSize.height)/2)); // 把文字作为遮罩,后续绘制只会在非文字区域生效 CGContextSaveGState(context); [progressText drawAtPoint:textPos withAttributes:textAttrs]; CGContextClip(context); // 绘制进度前景色,此时只有非文字区域会被填充 UIColor *foregroundColor = [UIColor whiteColor]; [foregroundColor setFill]; CGRect progressRect = CGRectMake(0, 0, self.progress * size.width, size.height); CGContextFillRect(context, progressRect); CGContextRestoreGState(context); }
为啥之前的方法失效了?
你之前把foregroundColor改成clearColor后,第一步画的文字完全透明,等于没画;然后裁剪未完成区域画白色背景+绿色文字,最后整个进度条就变成了绿色背景加未完成部分的白色,自然看不到文字镂空的效果。而上面两种方案都是围绕"让文字区域透出背景"来设计的,完美匹配你的需求。
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

