-
-
Save JohnEstropia/9482567 to your computer and use it in GitHub Desktop.
// | |
// JEProgressView.h | |
// | |
// | |
// Created by John Rommel Estropia on 2014/03/11. | |
// Copyright (c) 2014 John Rommel Estropia. | |
// | |
// Permission is hereby granted, free of charge, to any person obtaining a copy | |
// of this software and associated documentation files (the "Software"), to deal | |
// in the Software without restriction, including without limitation the rights | |
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
// copies of the Software, and to permit persons to whom the Software is | |
// furnished to do so, subject to the following conditions: | |
// | |
// The above copyright notice and this permission notice shall be included in | |
// all copies or substantial portions of the Software. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
// THE SOFTWARE. | |
// | |
#import <UIKit/UIKit.h> | |
// iOS 7.1 bugfix | |
// http://stackoverflow.com/questions/22311516/uiprogressview-custom-track-and-progress-images-in-ios-7-1 | |
@interface JEProgressView : UIProgressView | |
@end |
// | |
// JEProgressView.m | |
// | |
// | |
// Created by John Rommel Estropia on 2014/03/11. | |
// Copyright (c) 2014 John Rommel Estropia. | |
// | |
// Permission is hereby granted, free of charge, to any person obtaining a copy | |
// of this software and associated documentation files (the "Software"), to deal | |
// in the Software without restriction, including without limitation the rights | |
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
// copies of the Software, and to permit persons to whom the Software is | |
// furnished to do so, subject to the following conditions: | |
// | |
// The above copyright notice and this permission notice shall be included in | |
// all copies or substantial portions of the Software. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
// THE SOFTWARE. | |
// | |
#import "JEProgressView.h" | |
@interface JEProgressView () | |
@property (nonatomic, weak) UIImageView *trackImageView; | |
@property (nonatomic, weak) UIImageView *progressImageView; | |
@end | |
@implementation JEProgressView | |
#pragma mark - NSObject | |
- (id)initWithFrame:(CGRect)frame | |
{ | |
self = [super initWithFrame:frame]; | |
if (self) | |
{ | |
[self setupProgressView]; | |
} | |
return self; | |
} | |
- (id)initWithCoder:(NSCoder *)aDecoder | |
{ | |
self = [super initWithCoder:aDecoder]; | |
if (self) | |
{ | |
[self setupProgressView]; | |
} | |
return self; | |
} | |
#pragma mark - UIView | |
- (void)layoutSubviews | |
{ | |
[super layoutSubviews]; | |
UIImageView *trackImageView = self.trackImageView; | |
UIImageView *progressImageView = self.progressImageView; | |
if (!trackImageView || !progressImageView) | |
{ | |
return; | |
} | |
CGRect bounds = self.bounds; | |
CGFloat boundsTop = CGRectGetMinY(bounds); | |
UIImage *trackImage = self.trackImage; | |
if (trackImage) | |
{ | |
CGRect trackFrame = trackImageView.frame; | |
CGFloat trackHeight = trackImage.size.height; | |
trackImageView.frame = (CGRect){ | |
.origin.x = CGRectGetMinX(trackFrame), | |
.origin.y = (boundsTop | |
+ ((CGRectGetHeight(bounds) - trackHeight) * 0.5f)), | |
.size.width = CGRectGetWidth(trackFrame), | |
.size.height = trackHeight | |
}; | |
} | |
UIImage *progressImage = self.progressImage; | |
if (progressImage) | |
{ | |
CGRect progressFrame = progressImageView.frame; | |
CGFloat progressHeight = progressImage.size.height; | |
progressImageView.frame = (CGRect){ | |
.origin.x = CGRectGetMinX(progressFrame), | |
.origin.y = (boundsTop | |
+ ((CGRectGetHeight(bounds) - progressHeight) * 0.5f)), | |
.size.width = CGRectGetWidth(progressFrame), | |
.size.height = progressHeight | |
}; | |
} | |
} | |
#pragma mark - UIProgressView | |
- (void)setProgressImage:(UIImage *)progressImage | |
{ | |
[super setProgressImage:progressImage]; | |
self.progressImageView.image = progressImage; | |
} | |
- (void)setTrackImage:(UIImage *)trackImage | |
{ | |
[super setTrackImage:trackImage]; | |
self.trackImageView.image = trackImage; | |
} | |
#pragma mark - private | |
- (void)setupProgressView | |
{ | |
if ([self compareVersionString:[UIDevice currentDevice].systemVersion | |
withVersionString:@"7.1"] == NSOrderedAscending) | |
{ | |
return; | |
} | |
NSArray *subviews = self.subviews; | |
if ([subviews count] != 2) | |
{ | |
return; | |
} | |
for (UIView *subview in subviews) | |
{ | |
if (![subview isKindOfClass:[UIImageView class]]) | |
{ | |
return; | |
} | |
} | |
self.trackImageView = subviews[0]; | |
self.progressImageView = subviews[1]; | |
self.trackImageView.image = self.trackImage; | |
self.progressImageView.image = self.progressImage; | |
} | |
- (NSComparisonResult)compareVersionString:(NSString *)versionString1 | |
withVersionString:(NSString *)versionString2 | |
{ | |
NSArray *components1 = [versionString1 componentsSeparatedByString:@"."]; | |
NSArray *components2 = [versionString2 componentsSeparatedByString:@"."]; | |
NSUInteger components1Count = [components1 count]; | |
NSUInteger components2Count = [components2 count]; | |
NSUInteger partCount = MAX(components1Count, components2Count); | |
for (NSInteger part = 0; part < partCount; ++part) | |
{ | |
if (part >= components1Count) | |
{ | |
return NSOrderedAscending; | |
} | |
if (part >= components2Count) | |
{ | |
return NSOrderedDescending; | |
} | |
NSString *part1String = components1[part]; | |
NSString *part2String = components2[part]; | |
NSInteger part1 = [part1String integerValue]; | |
NSInteger part2 = [part2String integerValue]; | |
if (part1 > part2) | |
{ | |
return NSOrderedDescending; | |
} | |
if (part1 < part2) | |
{ | |
return NSOrderedAscending; | |
} | |
} | |
return NSOrderedSame; | |
} | |
@end |
@JohnEstropia
It works,but not works perfectly.
Here is a problem I met:
Present a JEProgressView on a controller's view.Then show a alertview (or a new window). The JEProgressView's apperance changes.progressTintColor turns to blue. (Sorry about my poor English,hope you can catch my meaning)
It seems (in my trial) that it doesn't work when setting a progressview up in a storyboard - the setProgressImage/TrackImage methods don't get called. If I set it up in code, those methods get called. (And I have changed the class of the progressView in the storyboard to the JEProgressView)
Cheers for your work on this!!
@JackTheNoob
as @httpsgithub mentioned above, you seem to also need to set
self.tintColor = [UIColor clearColor];
so your image doesn't turn blue. I'd automatically set the tintColor to clearColor if the images are not null, but I don't want to change the behavior of the original UIProgressView.
@mtancock
Probably because images in storyboards are set straight within -[initWithCoder:]. You did raise a common use case so I'll include a fix for this.
Problem: AlertView drops custom image from JEProgressView's ProgressImage and change it on default values (plane color). By the way TrackImage is ok.
Hi,
thanks for this fix. It totally fits my needs in a project.
Could you explain, why you calculate the origin on the y-axis of the image views the way you are doing it? With your original Code, the two imageViews will have an origin of -7.25 using images with a height of 17px, cause the heigth of the UIProgressView itself is 2,5px, even though I set a frame with a height of 17px.
When I change the line
.origin.y = (boundsTop + ((CGRectGetHeight(bounds) - trackHeight) * 0.5f)),
to
.origin.y = CGRectGetMinY(trackFrame),
the progress image view is positioned as expected. (I do not use an image for the track)
Regards
Oliver
@oklimberg: My computation makes it so that the imageViews are vertically centered within the parent UIProgressView.
works great.
Note: height of progressView is still set to 2., so remember to set progressBar.clipsToBounds=NO
Why not just
- (void)drawRect:(CGRect)rect {
double progress = MIN(1, MAX(0, self.progress));
[self.progressBackgroundImage drawInRect:rect];
CGRect progressFrame = rect;
progressFrame.size.width = round(rect.size.width * progress);
[self.progressImage drawInRect:progressFrame];
}
and not subclass UIProgressView
?
Hi,
I have been searching for the same solution for a long time, thanks. Can i make progress view round cornered at the corners.
@httpsgithub
I haven't tested this, but does the default UIProgressView ignore tintColor when using custom images? If so I'll update the code. Our project clears out tintColor explicitly so I didn't notice.
@mrga
I'm intending to add this to my JEToolkit repository which uses MIT license. I added the license statement in the .h and .m files for now.
@RyoAbe
MITライセンスです。.hと.mに入れておきました。