So I haven't done this yet, I'm trying to play out how to do this. So I make a UITableView and each cell has an associated NSTimer. Now in each custom UITableViewCell I have a UIProgressView as the background, stretched to fill the cell. Now I want to add a UILabel with remaining time onto of the UIProgressView. But since the progress bar fill color and background color are dramatically different (navy blue progress fill and white background/non filled area), I'm wondering how to dynamically change the text color as the progress bar gets filled. Like the part of the UILabel that is on the navy blue fill, the text color should be white. The part that is on the white background, the text should be black. Something like this, but in objective-c.
Just hacked this up for you :)
Here's a simulator result of ZWProgressView:
Here's an example usage:
#import "ViewController.h"
#import "ZWProgressView.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
ZWProgressView *progressView = [[ZWProgressView alloc] init];
progressView.frame = CGRectMake((self.view.bounds.size.width - 200) / 2.0, self.view.bounds.size.height / 2.0 - 25.0, 200, 50);
progressView.progress = 0.47;
[self.view addSubview:progressView];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
Note: masking code taken from:
Simply mask a UIView with a rectangle
The header file
#import <UIKit/UIKit.h>
@interface ZWProgressView : UIView
@property (nonatomic, assign) CGFloat progress;
@property (nonatomic, strong) UIColor *normalTextColor;
@property (nonatomic, strong) UIColor *maskedTextColor;
@property (nonatomic, strong) UIView *container;
@property (nonatomic, strong) UIView *progressBar;
@property (nonatomic, strong) UILabel *progressLabel;
@property (nonatomic, strong) UILabel *maskedProgressLabel;
@property (nonatomic, strong) UIView *mask;
@end
The implementation file
#import "ZWProgressView.h"
@interface ZWProgressView()
{
NSLayoutConstraint *progressBarWidthConstraint;
NSLayoutConstraint *progressBarMaskWidthConstraint;
}
@end
@implementation ZWProgressView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.frame = frame;
[self initView];
[self addAllConstraints];
}
return self;
}
-(void)initView
{
self.layer.cornerRadius = 2.0;
self.backgroundColor = [UIColor colorWithRed:0.85 green:0.85 blue:0.85 alpha:1.0];
self.normalTextColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1.0];
self.maskedTextColor = [UIColor whiteColor];
self.container = [[UIView alloc] init];
self.container.layer.borderWidth = 1.0;
self.container.layer.borderColor = [UIColor grayColor].CGColor;
self.container.backgroundColor = [UIColor whiteColor];
self.container.layer.cornerRadius = 3.0;
self.container.clipsToBounds = YES;
self.progressBar = [[UIView alloc] init];
self.progressBar.backgroundColor = [UIColor colorWithRed:0.2 green:0.3 blue:0.8 alpha:1.0];
self.progressLabel = [[UILabel alloc] init];
self.progressLabel.font = [UIFont fontWithName:@"Arial-BoldMT" size:30];
self.progressLabel.textAlignment = NSTextAlignmentCenter;
self.progressLabel.textColor = self.normalTextColor;
self.progressLabel.clipsToBounds = YES;
self.maskedProgressLabel = [[UILabel alloc] init];
self.maskedProgressLabel.font = self.progressLabel.font;
self.maskedProgressLabel.textAlignment = self.progressLabel.textAlignment;
self.maskedProgressLabel.textColor = self.maskedTextColor;
self.maskedProgressLabel.clipsToBounds = YES;
self.mask = [[UIView alloc] init];
[self.container addSubview:self.progressBar];
[self.container addSubview:self.progressLabel];
[self.container addSubview:self.maskedProgressLabel];
[self.container addSubview:self.mask];
[self addSubview:self.container];
}
-(void)addAllConstraints
{
self.container.translatesAutoresizingMaskIntoConstraints = NO;
self.progressBar.translatesAutoresizingMaskIntoConstraints = NO;
self.progressLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.maskedProgressLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.mask.translatesAutoresizingMaskIntoConstraints = NO;
id views = @{@"container": self.container, @"progressBar": self.progressBar, @"progressLabel": self.progressLabel, @"maskedProgressLabel": self.maskedProgressLabel, @"mask": self.mask};
// container constraint
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-5-[container]-5-|" options:0 metrics:nil views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-5-[container]-5-|" options:0 metrics:nil views:views]];
// progressBar constraint
[self.container addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[progressBar]" options:0 metrics:nil views:views]];
progressBarWidthConstraint = [NSLayoutConstraint constraintWithItem:self.progressBar attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0];
[self.container addConstraint:progressBarWidthConstraint];
[self.container addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[progressBar]|" options:0 metrics:nil views:views]];
// progressLabel constraint
[self.container addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[progressLabel]|" options:0 metrics:nil views:views]];
[self.container addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[progressLabel]|" options:0 metrics:nil views:views]];
// maskedProgressLabel constraint
[self.container addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[maskedProgressLabel]|" options:0 metrics:nil views:views]];
[self.container addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[maskedProgressLabel]|" options:0 metrics:nil views:views]];
// mask constraint
[self.container addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[mask]" options:0 metrics:nil views:views]];
[self.container addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[mask]|" options:0 metrics:nil views:views]];
progressBarMaskWidthConstraint = [NSLayoutConstraint constraintWithItem:self.mask attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0];
[self.container addConstraint:progressBarMaskWidthConstraint];
}
-(void)setProgress:(CGFloat)progress
{
int percentage = progress * 100;
NSString *strProgress = [[NSString alloc] initWithFormat:@"%d%%", percentage];
self.progressLabel.text = strProgress;
self.maskedProgressLabel.text = strProgress;
// ------------------------------------------------------------------
// subtracting 10 pixel for the |-5-[progressBar]-5-| padding in
// the constraint for the progresBar
// ------------------------------------------------------------------
progressBarWidthConstraint.constant = progress * (self.bounds.size.width - 10.0);
progressBarMaskWidthConstraint.constant = progressBarWidthConstraint.constant;
[self layoutIfNeeded];
[self updateMask];
}
-(void)updateMask
{
// ------------------------------------------------------------------------
// Masking code taken from:
//
// https://stackoverflow.com/questions/11391058/simply-mask-a-uiview-with-a-rectangle
// ------------------------------------------------------------------------
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
CGRect maskRect = CGRectMake(0, 0, progressBarMaskWidthConstraint.constant, self.mask.bounds.size.height);
CGPathRef path = CGPathCreateWithRect(maskRect, NULL);
maskLayer.path = path;
CGPathRelease(path);
self.maskedProgressLabel.layer.mask = maskLayer;
}
@end