问题
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.
回答1:
Just hacked this up for you :)
The Result
Here's a simulator result of ZWProgressView:
The View Controller File
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
The ZWProgressView Class
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
回答2:
You can do this easily using two UILabels, one with the text color before, and one with the text color after. They should be exactly on top of each other. You can then shrink the width of the label on top corresponding to the timer and the label on the bottom will start to show. This should give you the effect you are looking for.
来源:https://stackoverflow.com/questions/24275603/uilabel-over-uiprogressview-with-multiple-colors