Skip to content

Instantly share code, notes, and snippets.

@BigAB
Created December 12, 2013 22:46
Show Gist options
  • Save BigAB/7936926 to your computer and use it in GitHub Desktop.
Save BigAB/7936926 to your computer and use it in GitHub Desktop.
A nice little customizable view for a progress bar, with optional animation properties
//
// ABProgressBar.h
// Adam L Barrett
//
// Created by Adam L Barrett on 2013-12-10.
// Copyright (c) 2013 Adam L Barrett. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
@interface GBProgressBar : UIView
@property (nonatomic, assign) double progress;
@property (nonatomic, strong) UIColor *color;
@property (nonatomic, strong) NSString *statusText;
@property (nonatomic, strong) UIColor *textColor;
@property (nonatomic, strong) NSNumber *fontSize;
@property (nonatomic, assign) CGPoint textOffset;
@property (nonatomic, assign) UIEdgeInsets contentInsets;
@property (nonatomic, assign, getter = isAnimated) BOOL animated;
@property (nonatomic, assign) NSTimeInterval animationDuration; // default 1.0
// This will slide up from Zero on appearance of the progress bar
@property (nonatomic, assign) BOOL animateFromZero;
// Animation easing effect
@property (nonatomic, strong) CAMediaTimingFunction *timingFunction;
@end
//
// ABProgressBar.m
// Adam L Barrett
//
// Created by Adam L Barrett on 2013-12-10.
// Copyright (c) 2013 Adam L Barrett. All rights reserved.
//
#import "GBProgressBar.h"
@interface GBProgressBar()
@property (nonatomic, strong) UILabel *statusTextLabel;
@property (nonatomic, strong) CALayer *progressLayer;
@end
@implementation GBProgressBar
@synthesize textColor = _textColor;
@synthesize fontSize = _fontSize;
@synthesize statusText = _statusText;
#pragma mark - Property Accessors
- (void)setProgress:(double)progress
{
_progress = progress;
[self updateStatusText];
if (self.animated) {
[self animateProgressLayerToProgress:_progress];
}
else {
[self setProgressLayerToProgress:_progress];
}
}
- (void)setColor:(UIColor *)color
{
if (![_color isEqual:color]) {
_color = color;
self.progressLayer.backgroundColor = _color.CGColor;
[self setNeedsDisplay];
}
}
- (UILabel *)statusTextLabel
{
if (!_statusTextLabel) {
_statusTextLabel = [[UILabel alloc] init];
_statusTextLabel.contentMode = UIViewContentModeRedraw;
_statusTextLabel.backgroundColor = [UIColor clearColor];
_statusTextLabel.textColor = self.textColor;
_statusTextLabel.numberOfLines = 1;
_statusTextLabel.adjustsFontSizeToFitWidth = YES;
if ([_statusText respondsToSelector:@selector(setMinimumScaleFactor:)]) {
_statusTextLabel.minimumScaleFactor = 0.2;
} else {
_statusTextLabel.minimumFontSize = 8.0;
}
_statusTextLabel.font = [UIFont fontWithName:@"Helvetica" size:[self.fontSize floatValue]];
_statusTextLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:self.statusTextLabel];
}
return _statusTextLabel;
}
- (UIColor *)textColor
{
if (!_textColor) {
_textColor = [UIColor whiteColor];
}
return _textColor;
}
- (void)setTextColor:(UIColor *)textColor
{
if (![_textColor isEqual:textColor]) {
_textColor = textColor;
self.statusTextLabel.textColor = _textColor;
}
}
- (NSString *)statusText
{
if (!_statusText) {
return @"%d%%";
}
return _statusText;
}
- (void)setStatusText:(NSString *)statusText
{
if (![_statusText isEqualToString:statusText]) {
_statusText = statusText;
[self updateStatusText];
[self setNeedsDisplay];
}
}
- (NSNumber *)fontSize
{
if (!_fontSize) {
return @20;
}
return _fontSize;
}
- (void)setFontSize:(NSNumber *)fontSize
{
if (![_fontSize isEqualToNumber:fontSize]) {
_fontSize = fontSize;
self.statusTextLabel.font = [UIFont fontWithName:@"Helvetica" size:[_fontSize floatValue]];
}
}
- (CALayer *)progressLayer
{
if (!_progressLayer) {
_progressLayer = [CALayer layer];
_progressLayer.anchorPoint = CGPointZero;
_progressLayer.backgroundColor = self.color.CGColor;
CGRect b = _progressLayer.bounds;
b.size.height = self.layer.bounds.size.height;
b.size.width = 0;
_progressLayer.bounds = b;
[self.layer insertSublayer:_progressLayer atIndex:0];
}
return _progressLayer;
}
#pragma mark - Init
- (void)_init
{
self.clipsToBounds = YES;
self.contentInsets = UIEdgeInsetsMake(5, 20, 5, 20);
self.progress = 0;
self.animationDuration = 1.0;
}
- (id)init
{
self = [super init];
if (self) {
[self _init];
}
return self;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self _init];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self _init];
}
return self;
}
#pragma mark - Updating Text Label
- (void)updateStatusText
{
self.statusTextLabel.text = [NSString stringWithFormat:self.statusText, (int)(self.progress * 100)];
}
#pragma mark - Layout
- (void)layoutSubviews
{
[super layoutSubviews];
CGRect b = self.bounds;
// Status Text Label
CGRect stlf = CGRectMake(0, 0, b.size.width, b.size.height);
stlf = UIEdgeInsetsInsetRect(stlf, self.contentInsets);
self.statusTextLabel.frame = stlf;
self.statusTextLabel.center = CGPointMake(CGRectGetMidX(b)+self.textOffset.x, CGRectGetMidY(b)+self.textOffset.y);
}
- (void)animateProgressLayerToProgress:(double)progress
{
if (self.animateFromZero) {
[self performBlock:^(id sender) {
[self setProgressLayerToProgress:progress];
} afterDelay:0];
}
else {
[self setProgressLayerToProgress:progress];
}
}
- (void)setProgressLayerToProgress:(double)progress
{
[CATransaction begin];
[CATransaction setAnimationDuration: ([self isAnimated] ? self.animationDuration : 0.0)];
if (self.timingFunction) {
[CATransaction setAnimationTimingFunction:self.timingFunction];
}
if ( ![self isAnimated] ) {
[CATransaction setDisableActions:YES];
}
// Transaction
CGRect b = self.progressLayer.bounds;
b.size.width = self.bounds.size.width * _progress;
self.progressLayer.bounds = b;
[CATransaction commit];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment