Initial commit
This commit is contained in:
Executable
+803
@@ -0,0 +1,803 @@
|
||||
//
|
||||
// MMHud.m
|
||||
// MMProgressHUD
|
||||
//
|
||||
// Created by Lars Anderson on 6/28/12.
|
||||
// Copyright (c) 2012 Mutual Mobile. All rights reserved.
|
||||
//
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#import "MMHud.h"
|
||||
#import "MMProgressHUD.h"
|
||||
#import "MMProgressHUDCommon.h"
|
||||
#import "MMProgressView-Protocol.h"
|
||||
#import "MMRadialProgressView.h"
|
||||
|
||||
CGFloat const MMProgressHUDDefaultFontSize = 16.f;
|
||||
|
||||
CGFloat const MMProgressHUDMaximumWidth = 300.f;
|
||||
CGFloat const MMProgressHUDMinimumWidth = 100.f;
|
||||
CGFloat const MMProgressHUDContentPadding = 5.f;
|
||||
|
||||
CGFloat const MMProgressHUDAnimateInDurationLong = 1.5f;
|
||||
CGFloat const MMProgressHUDAnimateInDurationMedium = 0.75f;
|
||||
CGFloat const MMProgressHUDAnimateInDurationNormal = 0.35f;
|
||||
CGFloat const MMProgressHUDAnimateInDurationShort = 0.25f;
|
||||
CGFloat const MMProgressHUDAnimateInDurationVeryShort= 0.15f;
|
||||
|
||||
CGFloat const MMProgressHUDAnimateOutDurationLong = 0.75f;
|
||||
CGFloat const MMProgressHUDAnimateOutDurationMedium = 0.55f;
|
||||
CGFloat const MMProgressHUDAnimateOutDurationShort = 0.35f;
|
||||
|
||||
CGSize const MMProgressHUDDefaultContentAreaSize = { 100.f, 100.f };
|
||||
CGSize const MMProgressHUDProgressContentAreaSize = { 40.f, 40.f };
|
||||
CGSize const MMProgressHUDProgressMaximumAreaSize = {200.0f, 200.0f};
|
||||
|
||||
|
||||
NSString * const MMProgressHUDFontNameBold = @"HelveticaNeue-Bold";
|
||||
//NSString * const MMProgressHUDFontNameNormal = @"HelveticaNeue-Light";
|
||||
NSString * const MMProgressHUDFontNameNormal = @"Chalkduster";
|
||||
@interface MMHud()
|
||||
|
||||
@property (nonatomic, strong) UIView *progressViewContainer;
|
||||
@property (nonatomic, strong) UIView <MMProgressView> *progressView;
|
||||
@property (nonatomic, readwrite, getter = isVisible) BOOL visible;
|
||||
@property (nonatomic, strong, readwrite) UIActivityIndicatorView *activityIndicator;
|
||||
@property (nonatomic, assign) CGRect contentAreaFrame;
|
||||
@property (nonatomic, assign) CGRect statusFrame;
|
||||
@property (nonatomic, assign) CGRect titleFrame;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MMHud
|
||||
|
||||
- (instancetype)init {
|
||||
if ( (self = [super init]) ) {
|
||||
_needsUpdate = YES;
|
||||
|
||||
self.indeterminate = YES;
|
||||
|
||||
[self configureInitialDisplayAttributes];
|
||||
|
||||
self.isAccessibilityElement = YES;
|
||||
self.progressViewClass = [MMRadialProgressView class];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
MMHudLog(@"dealloc");
|
||||
}
|
||||
|
||||
#pragma mark - Construction
|
||||
- (void)buildHUDAnimated:(BOOL)animated {
|
||||
if (animated == YES) {
|
||||
[UIView
|
||||
animateWithDuration:MMProgressHUDAnimateInDurationNormal
|
||||
animations:^{
|
||||
[self buildHUDAnimated:NO];
|
||||
}];
|
||||
}
|
||||
else {
|
||||
[self applyLayoutFrames];
|
||||
}
|
||||
}
|
||||
|
||||
- (CGSize)titleLabelSizeForTitleText:(NSString *)titleText {
|
||||
CGSize titleSize=CGSizeZero;
|
||||
NSInteger numberOfLines = 20;
|
||||
|
||||
CGFloat lineHeight;
|
||||
if ([self respondsToSelector:@selector(setTintColor:)]) {
|
||||
NSDictionary *attributes = @{NSFontAttributeName: self.titleLabel.font};
|
||||
lineHeight = [titleText sizeWithAttributes:attributes].height;
|
||||
}
|
||||
else{
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
lineHeight = [titleText sizeWithFont:self.titleLabel.font].height;
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
CGFloat targetWidthIncrementor = 25.f;
|
||||
for (CGFloat targetWidth = MMProgressHUDMinimumWidth; numberOfLines > 2; targetWidth += targetWidthIncrementor) {
|
||||
if (targetWidth >= MMProgressHUDMaximumWidth){
|
||||
break;
|
||||
}
|
||||
|
||||
CGSize boundingRect = CGSizeMake(targetWidth, 500.f);
|
||||
if ([self respondsToSelector:@selector(setTintColor:)]) {
|
||||
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
|
||||
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
|
||||
|
||||
NSDictionary *attributes = @{NSFontAttributeName: self.titleLabel.font,
|
||||
NSParagraphStyleAttributeName : paragraphStyle};
|
||||
|
||||
titleSize = [titleText boundingRectWithSize:boundingRect
|
||||
options:NSStringDrawingUsesLineFragmentOrigin
|
||||
attributes:attributes
|
||||
context:NULL].size;
|
||||
}
|
||||
else {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
titleSize = [titleText sizeWithFont:self.titleLabel.font
|
||||
constrainedToSize:boundingRect];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
numberOfLines = titleSize.height/lineHeight;
|
||||
}
|
||||
return titleSize;
|
||||
}
|
||||
|
||||
- (void)layoutContentAreaForCurrentState {
|
||||
if ((self.image || self.animationImages.count > 0) &&
|
||||
self.completionState == MMProgressHUDCompletionStateNone) {
|
||||
self.contentAreaFrame = CGRectMake(0.f,
|
||||
CGRectGetMaxY(self.titleFrame) + MMProgressHUDContentPadding,
|
||||
MMProgressHUDDefaultContentAreaSize.width,
|
||||
MMProgressHUDDefaultContentAreaSize.height);
|
||||
}
|
||||
else if (self.completionState == MMProgressHUDCompletionStateError ||
|
||||
self.completionState == MMProgressHUDCompletionStateSuccess) {
|
||||
UIImage *image = [self.delegate hud:self imageForCompletionState:self.completionState];
|
||||
self.contentAreaFrame = CGRectMake(0.f,
|
||||
CGRectGetMaxY(self.titleFrame) + MMProgressHUDContentPadding,
|
||||
image.size.width,
|
||||
image.size.height);
|
||||
}
|
||||
else {
|
||||
if (self.isIndeterminate) {
|
||||
self.contentAreaFrame = CGRectMake(0.f,
|
||||
CGRectGetMaxY(self.titleFrame) + MMProgressHUDContentPadding,
|
||||
CGRectGetWidth(self.activityIndicator.frame),
|
||||
CGRectGetHeight(self.activityIndicator.frame));
|
||||
}
|
||||
else {
|
||||
CGSize fittingSize = [[self progressViewClass] sizeThatFitsSize:MMProgressHUDProgressContentAreaSize maximumAvailableSize:MMProgressHUDProgressMaximumAreaSize];
|
||||
|
||||
self.contentAreaFrame = (CGRect) {{0.f,
|
||||
CGRectGetMaxY(self.titleFrame) + MMProgressHUDContentPadding}, fittingSize};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (CGSize)statusSizeForMessageText {
|
||||
CGSize statusSize = CGSizeZero;
|
||||
CGFloat additiveHeightConstant = 35.f;//35 is a fudge number from trial/error
|
||||
CGFloat targetWidthIncrementor = 25.f;
|
||||
for (CGFloat targetWidth = MMProgressHUDMinimumWidth; statusSize.width < statusSize.height + additiveHeightConstant; targetWidth += targetWidthIncrementor) {
|
||||
if (targetWidth >= MMProgressHUDMaximumWidth)
|
||||
break;
|
||||
|
||||
CGSize boundingRect = CGSizeMake(targetWidth, 500.f);
|
||||
if ([self respondsToSelector:@selector(setTintColor:)]) {
|
||||
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
|
||||
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
|
||||
|
||||
NSDictionary *attributes = @{NSFontAttributeName: self.statusLabel.font,
|
||||
NSParagraphStyleAttributeName : paragraphStyle};
|
||||
|
||||
statusSize = [self.messageText boundingRectWithSize:boundingRect
|
||||
options:NSStringDrawingUsesLineFragmentOrigin
|
||||
attributes:attributes
|
||||
context:NULL].size;
|
||||
}
|
||||
else {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
statusSize = [self.messageText sizeWithFont:self.statusLabel.font
|
||||
constrainedToSize:boundingRect];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
}
|
||||
return statusSize;
|
||||
}
|
||||
|
||||
- (void)layoutLabelFramesForStatusSize:(CGSize)statusSize titleSize:(CGSize)titleSize {
|
||||
CGFloat largerContentDimension = MAX(titleSize.width, statusSize.width);
|
||||
CGFloat upperBoundedContentWidth = MIN(largerContentDimension, MMProgressHUDMaximumWidth);
|
||||
CGFloat boundedContentWidth = MAX(upperBoundedContentWidth, MMProgressHUDMinimumWidth);
|
||||
CGFloat hudWidth = boundedContentWidth;
|
||||
|
||||
if (self.titleText) {
|
||||
self.titleFrame = CGRectIntegral(CGRectMake(self.titleFrame.origin.x,
|
||||
self.titleFrame.origin.y,
|
||||
hudWidth,
|
||||
self.titleFrame.size.height));
|
||||
}
|
||||
|
||||
if (self.messageText) {
|
||||
self.statusFrame = CGRectIntegral(CGRectMake(self.statusFrame.origin.x,
|
||||
self.statusFrame.origin.y,
|
||||
hudWidth,
|
||||
self.statusFrame.size.height));
|
||||
}
|
||||
}
|
||||
|
||||
- (void)layoutChildContentFramesForFinalHUDBounds:(CGRect)finalHudBounds {
|
||||
//center stuff
|
||||
self.titleFrame = CGRectMake(MMProgressHUDContentPadding,
|
||||
self.titleFrame.origin.y,
|
||||
CGRectGetWidth(finalHudBounds),
|
||||
CGRectGetHeight(self.titleFrame));
|
||||
self.statusFrame = CGRectMake(MMProgressHUDContentPadding,
|
||||
self.statusFrame.origin.y,
|
||||
CGRectGetWidth(finalHudBounds),
|
||||
CGRectGetHeight(self.statusFrame));
|
||||
self.contentAreaFrame = CGRectMake(CGRectGetWidth(finalHudBounds)/2
|
||||
- CGRectGetWidth(self.contentAreaFrame)/2
|
||||
+ MMProgressHUDContentPadding,
|
||||
self.contentAreaFrame.origin.y,
|
||||
CGRectGetWidth(self.contentAreaFrame),
|
||||
CGRectGetHeight(self.contentAreaFrame));
|
||||
|
||||
self.titleFrame = CGRectIntegral(self.titleFrame);
|
||||
self.statusFrame = CGRectIntegral(self.statusFrame);
|
||||
self.contentAreaFrame = CGRectIntegral(self.contentAreaFrame);
|
||||
}
|
||||
|
||||
- (void)updateLayoutFrames {
|
||||
|
||||
self.titleFrame = CGRectZero;
|
||||
self.statusFrame = CGRectZero;
|
||||
self.contentAreaFrame = CGRectZero;
|
||||
|
||||
CGSize titleSize = CGSizeZero;
|
||||
|
||||
if (self.titleText != nil) {
|
||||
titleSize = [self titleLabelSizeForTitleText:self.titleText];
|
||||
|
||||
self.titleFrame = CGRectMake(MMProgressHUDContentPadding,
|
||||
MMProgressHUDContentPadding,
|
||||
titleSize.width,
|
||||
titleSize.height);
|
||||
}
|
||||
|
||||
[self layoutContentAreaForCurrentState];
|
||||
|
||||
if (self.titleText == nil) {
|
||||
//adjust content area frame to compensate for extra padding that would have been around title label
|
||||
self.contentAreaFrame = CGRectOffset(self.contentAreaFrame,
|
||||
0.f,
|
||||
MMProgressHUDContentPadding);
|
||||
}
|
||||
|
||||
CGSize statusSize = CGSizeZero;
|
||||
if (self.messageText != nil) {
|
||||
statusSize = [self statusSizeForMessageText];
|
||||
|
||||
self.statusFrame = CGRectMake(MMProgressHUDContentPadding,
|
||||
CGRectGetMaxY(self.contentAreaFrame) + MMProgressHUDContentPadding,
|
||||
statusSize.width,
|
||||
statusSize.height);
|
||||
}
|
||||
|
||||
[self layoutLabelFramesForStatusSize:statusSize titleSize:titleSize];
|
||||
|
||||
CGRect imageTitleRect = CGRectUnion(self.titleFrame, self.contentAreaFrame);
|
||||
CGRect finalHudBounds = CGRectUnion(imageTitleRect, self.statusFrame);
|
||||
|
||||
[self layoutChildContentFramesForFinalHUDBounds:finalHudBounds];
|
||||
|
||||
[self _layoutContentArea];
|
||||
|
||||
self.needsUpdate = NO;
|
||||
}
|
||||
|
||||
- (void)configureInitialDisplayAttributes {
|
||||
// CGColorRef blackColor = CGColorRetain([UIColor blackColor].CGColor);
|
||||
|
||||
//self.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.75];
|
||||
// self.layer.shadowColor = blackColor;
|
||||
// self.layer.shadowOpacity = 0.5;
|
||||
// self.layer.shadowRadius = 15.0f;
|
||||
//self.layer.cornerRadius = 10.0f;
|
||||
// CGColorRelease(blackColor);
|
||||
self.backgroundColor=[UIColor clearColor];
|
||||
self.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
|
||||
}
|
||||
|
||||
- (void)frameInitialHUDPositionOffscreenWithDelegate:(id<MMHudDelegate>)localDelegate finalHudBounds:(CGRect)finalHudBounds {
|
||||
//create offscreen
|
||||
CGRect hudRect;
|
||||
CGPoint center = [localDelegate hudCenterPointForDisplay:self];
|
||||
|
||||
hudRect = CGRectMake(roundf(center.x - CGRectGetWidth(finalHudBounds)/2),
|
||||
roundf(-finalHudBounds.size.height*2),
|
||||
CGRectGetWidth(finalHudBounds),
|
||||
CGRectGetHeight(finalHudBounds));
|
||||
|
||||
|
||||
hudRect = CGRectIntegral(CGRectInset(hudRect, -MMProgressHUDContentPadding, -MMProgressHUDContentPadding));
|
||||
|
||||
self.frame = hudRect;
|
||||
|
||||
[self configureInitialDisplayAttributes];
|
||||
}
|
||||
|
||||
- (void)frameHUDPositionPreservingCenterWithDelegate:(id<MMHudDelegate>)localDelegate finalHudBounds:(CGRect)finalHudBounds {
|
||||
//preserve center
|
||||
CGRect hudRect;
|
||||
CGPoint center;
|
||||
if (self.isVisible) {
|
||||
center = [localDelegate hudCenterPointForDisplay:self];
|
||||
}
|
||||
else {
|
||||
center = self.center;
|
||||
}
|
||||
|
||||
CGFloat hudWidth = CGRectGetWidth(finalHudBounds);
|
||||
CGFloat hudHeight = CGRectGetHeight(finalHudBounds);
|
||||
CGFloat originX = roundf(center.x - self.layer.anchorPoint.x * hudWidth);
|
||||
CGFloat originYAnchorPointOffset = (0.5 - self.layer.anchorPoint.y) * 2.f * MMProgressHUDContentPadding;
|
||||
CGFloat originY = roundf(center.y - self.layer.anchorPoint.y * hudHeight + originYAnchorPointOffset);
|
||||
|
||||
hudRect = CGRectMake(originX, originY,
|
||||
hudWidth, hudHeight);
|
||||
|
||||
hudRect = CGRectIntegral(CGRectInset(hudRect, -MMProgressHUDContentPadding, -MMProgressHUDContentPadding));
|
||||
|
||||
self.frame = hudRect;
|
||||
}
|
||||
- (void)applyLayoutFrames {
|
||||
if (self.needsUpdate == YES) {
|
||||
[self updateLayoutFrames];
|
||||
}
|
||||
if (self.titleText == nil) {
|
||||
self.statusLabel.font = [UIFont fontWithName:MMProgressHUDFontNameBold
|
||||
size:MMProgressHUDDefaultFontSize];
|
||||
}
|
||||
else {
|
||||
self.statusLabel.font = [UIFont fontWithName:MMProgressHUDFontNameNormal
|
||||
size:MMProgressHUDDefaultFontSize];
|
||||
}
|
||||
//animate text change
|
||||
CATransition *crossfadeTransition = [CATransition animation];
|
||||
crossfadeTransition.duration = MMProgressHUDAnimateInDurationVeryShort;
|
||||
crossfadeTransition.type = kCATransitionFade;
|
||||
crossfadeTransition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
|
||||
|
||||
[self.titleLabel.layer addAnimation:crossfadeTransition forKey:@"changeTextTransition"];
|
||||
[self.statusLabel.layer addAnimation:crossfadeTransition forKey:@"changeTextTransition"];
|
||||
|
||||
self.titleLabel.text = self.titleText;
|
||||
self.statusLabel.text = self.messageText;
|
||||
|
||||
//update container
|
||||
CGRect imageTitleRect = CGRectUnion(self.titleFrame, self.contentAreaFrame);
|
||||
CGRect finalHudBounds = CGRectUnion(imageTitleRect, self.statusFrame);
|
||||
|
||||
id<MMHudDelegate> localDelegate = self.delegate;
|
||||
|
||||
if (CGRectEqualToRect(self.frame, CGRectZero) == NO) {
|
||||
[self frameHUDPositionPreservingCenterWithDelegate:localDelegate
|
||||
finalHudBounds:finalHudBounds];
|
||||
}
|
||||
else {
|
||||
[self frameInitialHUDPositionOffscreenWithDelegate:localDelegate
|
||||
finalHudBounds:finalHudBounds];
|
||||
}
|
||||
|
||||
//update subviews' frames
|
||||
self.titleLabel.frame = self.titleFrame;
|
||||
self.statusLabel.frame = self.statusFrame;
|
||||
self.progressViewContainer.frame = self.contentAreaFrame;
|
||||
|
||||
UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds
|
||||
cornerRadius:self.layer.cornerRadius];
|
||||
self.layer.shadowPath = shadowPath.CGPath;
|
||||
}
|
||||
|
||||
#pragma mark - Updating Content
|
||||
- (void)updateTitle:(NSString *)title animated:(BOOL)animated {
|
||||
self.titleText = title;
|
||||
|
||||
[self updateAnimated:animated withCompletion:nil];
|
||||
}
|
||||
|
||||
- (void)updateMessage:(NSString *)message animated:(BOOL)animated {
|
||||
self.messageText = message;
|
||||
|
||||
[self updateAnimated:animated withCompletion:nil];
|
||||
}
|
||||
|
||||
- (void)updateTitle:(NSString *)title message:(NSString *)message animated:(BOOL)animated {
|
||||
self.messageText = message;
|
||||
self.titleText = title;
|
||||
|
||||
[self updateAnimated:animated withCompletion:nil];
|
||||
}
|
||||
|
||||
- (void)updateAnimated:(BOOL)animated withCompletion:(void(^)(BOOL completed))updateCompletion {
|
||||
if (animated) {
|
||||
[UIView
|
||||
animateWithDuration:MMProgressHUDAnimateInDurationShort
|
||||
delay:0.f
|
||||
options:UIViewAnimationOptionCurveLinear
|
||||
animations:^{
|
||||
[self applyLayoutFrames];
|
||||
}
|
||||
completion:updateCompletion];
|
||||
}
|
||||
else {
|
||||
[self applyLayoutFrames];
|
||||
|
||||
if (updateCompletion != nil) {
|
||||
updateCompletion(YES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Private Methods
|
||||
- (UIViewContentMode)contentModeForImage:(UIImage *)image {
|
||||
//layout imageview content mode
|
||||
UIViewContentMode contentMode;
|
||||
CGFloat xRatio = image.size.width/CGRectGetWidth(self.imageView.frame);
|
||||
CGFloat yRatio = image.size.height/CGRectGetHeight(self.imageView.frame);
|
||||
if ((xRatio < 1.f) &&
|
||||
(yRatio < 1.f)) {
|
||||
contentMode = UIViewContentModeCenter;
|
||||
}
|
||||
else if ((xRatio > 1.f) &&
|
||||
(yRatio > 1.f)) {
|
||||
contentMode = UIViewContentModeScaleAspectFit;
|
||||
}
|
||||
else {
|
||||
contentMode = UIViewContentModeScaleAspectFill;
|
||||
}
|
||||
|
||||
return contentMode;
|
||||
}
|
||||
|
||||
- (void)_layoutContentArea {
|
||||
//hud should already be the correct size before getting into this method
|
||||
self.progressViewContainer.frame = self.contentAreaFrame;
|
||||
|
||||
self.imageView.hidden = (self.image == nil && self.animationImages.count == 0);
|
||||
self.progressView.hidden = self.isIndeterminate;
|
||||
|
||||
if (self.completionState == MMProgressHUDCompletionStateNone) {
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions:YES];
|
||||
|
||||
if (self.animationImages.count > 0) {
|
||||
self.imageView.image = nil;
|
||||
self.imageView.animationImages = self.animationImages;
|
||||
|
||||
[self.activityIndicator stopAnimating];
|
||||
|
||||
if (self.animationLoopDuration) {
|
||||
self.imageView.animationDuration = self.animationLoopDuration;
|
||||
}
|
||||
else {
|
||||
//图片运行时间
|
||||
self.imageView.animationDuration = 3.5;
|
||||
}
|
||||
|
||||
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
|
||||
|
||||
[self.imageView startAnimating];
|
||||
}
|
||||
else if (self.image != nil) {
|
||||
self.imageView.animationImages = nil;
|
||||
self.imageView.image = self.image;
|
||||
|
||||
[self.activityIndicator stopAnimating];
|
||||
|
||||
self.imageView.contentMode = [self contentModeForImage:self.imageView.image];
|
||||
}
|
||||
else {
|
||||
self.imageView.hidden = YES;
|
||||
|
||||
if (self.isIndeterminate) {
|
||||
[self.activityIndicator startAnimating];
|
||||
|
||||
self.imageView.image = nil;
|
||||
self.imageView.animationImages = nil;
|
||||
|
||||
[self.progressViewContainer addSubview:self.activityIndicator];
|
||||
}
|
||||
else {
|
||||
[self.activityIndicator stopAnimating];
|
||||
}
|
||||
}
|
||||
|
||||
[CATransaction commit];
|
||||
}
|
||||
else {
|
||||
UIImage *completionImage = [self.delegate hud:self imageForCompletionState:self.completionState];
|
||||
UIViewAnimationOptions animationOptions =
|
||||
UIViewAnimationOptionTransitionCrossDissolve |
|
||||
UIViewAnimationOptionBeginFromCurrentState |
|
||||
UIViewAnimationOptionCurveEaseInOut |
|
||||
UIViewAnimationOptionAllowAnimatedContent;
|
||||
|
||||
[UIView
|
||||
transitionWithView:self.progressViewContainer
|
||||
duration:MMProgressHUDAnimateInDurationVeryShort
|
||||
options:animationOptions
|
||||
animations:^{
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions:YES];
|
||||
{
|
||||
[self.imageView stopAnimating];
|
||||
|
||||
self.imageView.contentMode = [self contentModeForImage:completionImage];
|
||||
|
||||
[self.activityIndicator stopAnimating];
|
||||
self.progressView.hidden = YES;
|
||||
|
||||
self.imageView.image = completionImage;
|
||||
self.imageView.hidden = NO;
|
||||
}
|
||||
[CATransaction commit];
|
||||
}
|
||||
completion:nil];
|
||||
}
|
||||
|
||||
self.completionState = MMProgressHUDCompletionStateNone;
|
||||
}
|
||||
|
||||
- (void)_buildStatusLabel {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdirect-ivar-access"
|
||||
if (_statusLabel == nil) {
|
||||
_statusLabel = [[UILabel alloc] initWithFrame:CGRectZero];
|
||||
_statusLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
|
||||
_statusLabel.numberOfLines = 0;
|
||||
if ([UICollectionView class]) {
|
||||
_statusLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
||||
_statusLabel.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
else{
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
_statusLabel.lineBreakMode = UILineBreakModeWordWrap;
|
||||
_statusLabel.textAlignment = UITextAlignmentCenter;
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
_statusLabel.backgroundColor = [UIColor clearColor];
|
||||
_statusLabel.font = [UIFont fontWithName:MMProgressHUDFontNameNormal size:MMProgressHUDDefaultFontSize];
|
||||
//_statusLabel.textColor = [UIColor colorWithWhite:0.9f alpha:0.95f];
|
||||
// _statusLabel.textColor = COLOR_LABEL_TITLE;
|
||||
// _statusLabel.shadowColor = [UIColor blackColor];
|
||||
// _statusLabel.shadowOffset = CGSizeMake(0, -1);
|
||||
|
||||
#ifdef MM_HUD_FRAME_DEBUG
|
||||
CGColorRef redColor = CGColorRetain([UIColor redColor].CGColor);
|
||||
|
||||
_statusLabel.layer.borderColor = redColor;
|
||||
_statusLabel.layer.borderWidth = 1.f;
|
||||
|
||||
CGColorRelease(redColor);
|
||||
#endif
|
||||
|
||||
[self addSubview:_statusLabel];
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
- (void)_buildTitleLabel {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdirect-ivar-access"
|
||||
if (_titleLabel == nil) {
|
||||
_titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
|
||||
_titleLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
|
||||
_titleLabel.numberOfLines = 0;
|
||||
if ([UICollectionView class]) {
|
||||
_titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
||||
_titleLabel.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
else{
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
_titleLabel.lineBreakMode = UILineBreakModeWordWrap;
|
||||
_titleLabel.textAlignment = UITextAlignmentCenter;
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
_titleLabel.backgroundColor = [UIColor clearColor];
|
||||
_titleLabel.font = [UIFont fontWithName:MMProgressHUDFontNameBold size:MMProgressHUDDefaultFontSize];
|
||||
_titleLabel.textColor = [UIColor whiteColor];
|
||||
_titleLabel.shadowColor = [UIColor blackColor];
|
||||
_titleLabel.shadowOffset = CGSizeMake(0, -1);
|
||||
|
||||
#ifdef MM_HUD_FRAME_DEBUG
|
||||
CGColorRef blueColor = CGColorRetain([UIColor blueColor].CGColor);
|
||||
|
||||
_titleLabel.layer.borderColor = blueColor;
|
||||
_titleLabel.layer.borderWidth = 1.f;
|
||||
|
||||
CGColorRelease(blueColor);
|
||||
#endif
|
||||
|
||||
[self addSubview:_titleLabel];
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
#pragma mark - Property Overrides
|
||||
- (void)setProgressStyle:(MMProgressHUDProgressStyle)progressStyle {
|
||||
_progressStyle = progressStyle;
|
||||
|
||||
MMHudWLog(@"Setting %@ is deprecated, please set an explicit determinate progress class using %@",
|
||||
NSStringFromSelector(@selector(progressStyle)),
|
||||
NSStringFromSelector(@selector(progressViewClass)));
|
||||
|
||||
self.indeterminate = (progressStyle == MMProgressHUDProgressStyleIndeterminate);
|
||||
}
|
||||
|
||||
- (void)setProgressViewClass:(Class)progressViewClass {
|
||||
if (progressViewClass != Nil) {
|
||||
Protocol * __unused expectedProtocol = @protocol(MMProgressView);
|
||||
|
||||
NSAssert([progressViewClass conformsToProtocol:expectedProtocol], @"Class %@ doesn't conform to %@ protocol", NSStringFromClass(progressViewClass), NSStringFromProtocol(expectedProtocol));
|
||||
}
|
||||
else {
|
||||
[self setIndeterminate:YES];
|
||||
}
|
||||
|
||||
_progressViewClass = progressViewClass;
|
||||
}
|
||||
|
||||
- (UIImageView *)imageView {
|
||||
if (_imageView == nil) {//
|
||||
_imageView = [[UIImageView alloc] initWithFrame:self.progressViewContainer.bounds];
|
||||
_imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
_imageView.contentMode = UIViewContentModeCenter;
|
||||
[self.progressViewContainer addSubview:_imageView];
|
||||
}
|
||||
|
||||
return _imageView;
|
||||
}
|
||||
|
||||
- (UIView <MMProgressView> *)progressView {
|
||||
if (_progressView == nil ||
|
||||
(_progressView.class != self.progressViewClass)) {
|
||||
_progressView = [[self.progressViewClass alloc] initWithFrame:self.progressViewContainer.bounds];
|
||||
_progressView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
[self.progressViewContainer addSubview:_progressView];
|
||||
}
|
||||
|
||||
return _progressView;
|
||||
}
|
||||
|
||||
- (UIView *)progressViewContainer {
|
||||
if (_progressViewContainer == nil) {
|
||||
_progressViewContainer = [[UIView alloc] initWithFrame:self.contentAreaFrame];
|
||||
_progressViewContainer.backgroundColor = [UIColor clearColor];
|
||||
|
||||
#ifdef MM_HUD_FRAME_DEBUG
|
||||
CGColorRef yellowColor = CGColorRetain([UIColor yellowColor].CGColor);
|
||||
|
||||
_progressViewContainer.layer.borderColor = yellowColor;
|
||||
_progressViewContainer.layer.borderWidth = 1.f;
|
||||
|
||||
CGColorRelease(yellowColor);
|
||||
#endif
|
||||
|
||||
[self addSubview:_progressViewContainer];
|
||||
}
|
||||
|
||||
return _progressViewContainer;
|
||||
}
|
||||
|
||||
- (UIActivityIndicatorView *)activityIndicator {
|
||||
if (_activityIndicator == nil) {
|
||||
_activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
|
||||
|
||||
_activityIndicator.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
|
||||
_activityIndicator.hidesWhenStopped = YES;
|
||||
}
|
||||
return _activityIndicator;
|
||||
}
|
||||
|
||||
- (void)setProgress:(CGFloat)progress {
|
||||
[self setProgress:progress animated:YES];
|
||||
}
|
||||
|
||||
- (void)setProgress:(CGFloat)progress animated:(BOOL)animated {
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdirect-ivar-access"
|
||||
_progress = progress;
|
||||
|
||||
__typeof(self) __weak weakSelf = self;
|
||||
|
||||
void(^completionBlock)(BOOL completed) = ^(BOOL completed) {
|
||||
MMHud *blockSelf = weakSelf;
|
||||
id blockDelegate = blockSelf.delegate;
|
||||
|
||||
if ( (completed == YES) &&
|
||||
(progress >= 1.f) &&
|
||||
([blockDelegate respondsToSelector:@selector(hudDidCompleteProgress:)] == YES)) {
|
||||
[blockDelegate hudDidCompleteProgress:blockSelf];
|
||||
}
|
||||
};
|
||||
|
||||
[self.progressView setProgress:progress
|
||||
animated:animated
|
||||
withCompletion:completionBlock];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
- (void)setIndeterminate:(BOOL)indeterminate {
|
||||
if (!indeterminate && self.progressViewClass == Nil) {
|
||||
MMHudWLog(@"HUD %@ set to determinate progress but progress view class is Nil", self);
|
||||
}
|
||||
|
||||
if (indeterminate != self.isIndeterminate) {
|
||||
_indeterminate = indeterminate;
|
||||
[self setNeedsUpdate:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (UILabel *)statusLabel {
|
||||
[self _buildStatusLabel];
|
||||
|
||||
return _statusLabel;
|
||||
}
|
||||
|
||||
- (UILabel *)titleLabel {
|
||||
[self _buildTitleLabel];
|
||||
|
||||
return _titleLabel;
|
||||
}
|
||||
|
||||
- (void)setMessageText:(NSString *)messageText {
|
||||
if ([messageText isEqualToString:self.messageText]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_messageText = [messageText copy];
|
||||
if (self.titleText == nil) {
|
||||
self.accessibilityLabel = _messageText;
|
||||
}
|
||||
else {
|
||||
self.accessibilityHint = _messageText;
|
||||
}
|
||||
|
||||
[self setNeedsUpdate:YES];
|
||||
}
|
||||
|
||||
- (void)setTitleText:(NSString *)titleText {
|
||||
if ([titleText isEqualToString:self.titleText]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_titleText = [titleText copy];
|
||||
|
||||
self.accessibilityLabel = _titleText;
|
||||
|
||||
[self setNeedsUpdate:YES];
|
||||
}
|
||||
|
||||
- (void)setDisplayStyle:(MMProgressHUDDisplayStyle)style {
|
||||
_displayStyle = style;
|
||||
|
||||
switch (style) {
|
||||
case MMProgressHUDDisplayStyleBordered:{
|
||||
CGColorRef whiteColor = CGColorRetain([UIColor whiteColor].CGColor);
|
||||
self.layer.borderColor = whiteColor;
|
||||
self.layer.borderWidth = 2.0f;
|
||||
CGColorRelease(whiteColor);
|
||||
}
|
||||
break;
|
||||
case MMProgressHUDDisplayStylePlain:
|
||||
self.layer.borderWidth = 0.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)prepareForReuse {
|
||||
self.titleLabel.text = nil;
|
||||
self.statusLabel.text = nil;
|
||||
self.imageView.image = nil;
|
||||
self.imageView.animationImages = nil;
|
||||
self.progress = 0.f;
|
||||
self.layer.transform = CATransform3DIdentity;
|
||||
self.layer.opacity = 1.f;
|
||||
self.completionState = MMProgressHUDCompletionStateNone;
|
||||
self.visible = NO;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user