UILabel:背景相关的颜色

我试图寻找这个问题的解决scheme,但我甚至无法用言语正确地说出来。

基本上我有一个酒吧,在操作过程中被填充颜色。 我有一个具有相同颜色的进度百分比的标签具有填充颜色,所以我需要它在填充颜色背面时进行更改。 像这样的东西:

在这里输入图像说明

是否有可能实现这个结果? 而且万一,怎么样?

最简单的方法是创build一个具有progress属性并覆盖-drawRect:UIView子类。

所有你需要的代码是这样的:

 - (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); // Set up environment. CGSize size = [self bounds].size; UIColor *backgroundColor = [UIColor colorWithRed:108.0/255.0 green:200.0/255.0 blue:226.0/255.0 alpha:1.0]; UIColor *foregroundColor = [UIColor whiteColor]; UIFont *font = [UIFont boldSystemFontOfSize:42.0]; // Prepare progress as a string. NSString *progress = [NSString stringWithFormat:@"%d%%", (int)round([self progress] * 100)]; NSMutableDictionary *attributes = [@{ NSFontAttributeName : font } mutableCopy]; CGSize textSize = [progress sizeWithAttributes:attributes]; CGFloat progressX = ceil([self progress] * size.width); CGPoint textPoint = CGPointMake(ceil((size.width - textSize.width) / 2.0), ceil((size.height - textSize.height) / 2.0)); // Draw background + foreground text [backgroundColor setFill]; CGContextFillRect(context, [self bounds]); attributes[NSForegroundColorAttributeName] = foregroundColor; [progress drawAtPoint:textPoint withAttributes:attributes]; // Clip the drawing that follows to the remaining progress' frame. CGContextSaveGState(context); CGRect remainingProgressRect = CGRectMake(progressX, 0.0, size.width - progressX, size.height); CGContextAddRect(context, remainingProgressRect); CGContextClip(context); // Draw again with inverted colors. [foregroundColor setFill]; CGContextFillRect(context, [self bounds]); attributes[NSForegroundColorAttributeName] = backgroundColor; [progress drawAtPoint:textPoint withAttributes:attributes]; CGContextRestoreGState(context); } - (void)setProgress:(CGFloat)progress { _progress = fminf(1.0, fmaxf(progress, 0.0)); [self setNeedsDisplay]; } 

您可以根据需要使用背景颜色,文本颜色,字体等属性来扩展该类。

两个UIViews。

  1. 我们来调用一个背景,另一个调用progressBar。 progressBar堆叠在背景上,并且在共同的超级视图上具有相同的来源。

  2. 他们都有一个UILabel作为子视图,并且两个标签的父母相同。 背景有一个黑暗的backgroundColor,它的标签具有light textColor和进度视图有相反的东西。

  3. progressBar具有比背景更窄的框架宽度,并具有clipsToBounds == YES

诀窍是,观点的起源相同,标签的起源相同,在顶视图上的clipsToBounds,一切看起来都是正确的。

将这两个视图放到一个名为ReallyCoolProgressView的新的UIView子类中,并给它一个公共方法:

 -(void)setProgress:(float)progress 

进度是一个从0.0到1.0的数字。 该方法缩放progressBar宽度并设置标签的文本@“Progress%f”,progress * 100

只是一个“伪装”你想要的效果的想法。 你可以用一个背景标签(白色和蓝色文本)和一个子视图创build一个UIView的子类,前面有蓝色背景色和白色文本。 您可以在背景标签上的前标签的宽度从0到100%之间animation。 您可能需要检查是否需要在子视图中标记标签,以避免文本移位,同时增加宽度。

为了让它更容易,不用重写drawRect:你可以创build2个UIView来解决这个问题。

蓝色背景UIView(A)包含白色的UILabel。 (剪切子视图打开)

白色背景UIView(B)包含蓝色的UILabel。

A会叠加在B.

注意:2个UILabel将有相同的大小,相同的字体和相同的位置。

通过调整UIView A的宽度,您将使进程栏按照您的意愿工作。

斯威夫特4版的莫滕的回答:

 class ProgressLabel: UIView { var progressBarColor = UIColor(red:108.0/255.0, green:200.0/255.0, blue:226.0/255.0, alpha:1.0) var textColor = UIColor.white var font = UIFont.boldSystemFont(ofSize: 42) var progress: Float = 0 { didSet { progress = Float.minimum(100.0, Float.maximum(progress, 0.0)) self.setNeedsDisplay() } } override func draw(_ rect: CGRect) { let context = UIGraphicsGetCurrentContext()! // Set up environment. let size = self.bounds.size // Prepare progress as a string. let progressMessage = NSString(format:"%d %%", Int(progress)) var attributes: [NSAttributedStringKey:Any] = [ NSAttributedStringKey.font : font ] let textSize = progressMessage.size(withAttributes: attributes) let progressX = ceil(CGFloat(progress) / 100 * size.width) let textPoint = CGPoint(x: ceil((size.width - textSize.width) / 2.0), y: ceil((size.height - textSize.height) / 2.0)) // Draw background + foreground text progressBarColor.setFill() context.fill(self.bounds) attributes[NSAttributedStringKey.foregroundColor] = textColor progressMessage.draw(at: textPoint, withAttributes: attributes) // Clip the drawing that follows to the remaining progress' frame. context.saveGState() let remainingProgressRect = CGRect(x: progressX, y: 0.0, width: size.width - progressX, height: size.height) context.addRect(remainingProgressRect) context.clip() // Draw again with inverted colors. textColor.setFill() context.fill(self.bounds) attributes[NSAttributedStringKey.foregroundColor] = progressBarColor progressMessage.draw(at: textPoint, withAttributes: attributes) context.restoreGState() } } 

最好的和最干净的方法是使用口罩。 进度条的视图层次结构应该如下所示:

  • 基础
    • Subview at index #1视图显示进度
    • Subview at index #2 UILabel的文本颜色与基本相同
    • Subview at index #3 UILabel的文本颜色与显示进度的视图相同

我们将使用面具#3 。 一旦显示进度的视图到达#3的框架,我们就开始使用掩码。 面具的框架必须遵循进度。 当#3逐渐被掩盖时,下面的标签就会显示出来,而且您可以很轻松的达到效果。 在这里你是如何创build与CALayers面具 。