对MBProgressHUD进行二次封装并精简使用
对MBProgressHUD进行二次封装并精简使用
https://github.com/jdg/MBProgressHUD
几个效果图:
以下源码是MBProgressHUD支持最新的iOS8的版本,没有任何的警告信息
MBProgressHUD.h 与 MBProgressHUD.m
![](/assets/blank.gif)
![](/assets/blank.gif)
// // MBProgressHUD.h // Version 0.9 // Created by Matej Bukovinski on 2.4.09. //// This code is distributed under the terms and conditions of the MIT license. // Copyright (c) 2013 Matej Bukovinski // // 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 <Foundation/Foundation.h> #import <UIKit/UIKit.h> #import <CoreGraphics/CoreGraphics.h>@protocol MBProgressHUDDelegate;typedef enum {/** Progress is shown using an UIActivityIndicatorView. This is the default. */MBProgressHUDModeIndeterminate,/** Progress is shown using a round, pie-chart like, progress view. */MBProgressHUDModeDeterminate,/** Progress is shown using a horizontal progress bar */MBProgressHUDModeDeterminateHorizontalBar,/** Progress is shown using a ring-shaped progress view. */MBProgressHUDModeAnnularDeterminate,/** Shows a custom view */MBProgressHUDModeCustomView,/** Shows only labels */MBProgressHUDModeText } MBProgressHUDMode;typedef enum {/** Opacity animation */MBProgressHUDAnimationFade,/** Opacity + scale animation */MBProgressHUDAnimationZoom,MBProgressHUDAnimationZoomOut = MBProgressHUDAnimationZoom,MBProgressHUDAnimationZoomIn } MBProgressHUDAnimation;#ifndef MB_INSTANCETYPE #if __has_feature(objc_instancetype)#define MB_INSTANCETYPE instancetype #else#define MB_INSTANCETYPE id #endif #endif#ifndef MB_STRONG #if __has_feature(objc_arc)#define MB_STRONG strong #else#define MB_STRONG retain #endif #endif#ifndef MB_WEAK #if __has_feature(objc_arc_weak)#define MB_WEAK weak #elif __has_feature(objc_arc)#define MB_WEAK unsafe_unretained #else#define MB_WEAK assign #endif #endif#if NS_BLOCKS_AVAILABLE typedef void (^MBProgressHUDCompletionBlock)(); #endif/** * Displays a simple HUD window containing a progress indicator and two optional labels for short messages.** This is a simple drop-in class for displaying a progress HUD view similar to Apple's private UIProgressHUD class.* The MBProgressHUD window spans over the entire space given to it by the initWithFrame constructor and catches all* user input on this region, thereby preventing the user operations on components below the view. The HUD itself is* drawn centered as a rounded semi-transparent view which resizes depending on the user specified content.** This view supports four modes of operation:* - MBProgressHUDModeIndeterminate - shows a UIActivityIndicatorView* - MBProgressHUDModeDeterminate - shows a custom round progress indicator* - MBProgressHUDModeAnnularDeterminate - shows a custom annular progress indicator* - MBProgressHUDModeCustomView - shows an arbitrary, user specified view (@see customView)** All three modes can have optional labels assigned:* - If the labelText property is set and non-empty then a label containing the provided content is placed below the* indicator view.* - If also the detailsLabelText property is set then another label is placed below the first label.*/ @interface MBProgressHUD : UIView/*** Creates a new HUD, adds it to provided view and shows it. The counterpart to this method is hideHUDForView:animated:.* * @param view The view that the HUD will be added to* @param animated If set to YES the HUD will appear using the current animationType. If set to NO the HUD will not use* animations while appearing.* @return A reference to the created HUD.** @see hideHUDForView:animated:* @see animationType*/ + (MB_INSTANCETYPE)showHUDAddedTo:(UIView *)view animated:(BOOL)animated;/*** Finds the top-most HUD subview and hides it. The counterpart to this method is showHUDAddedTo:animated:.** @param view The view that is going to be searched for a HUD subview.* @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use* animations while disappearing.* @return YES if a HUD was found and removed, NO otherwise. ** @see showHUDAddedTo:animated:* @see animationType*/ + (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated;/*** Finds all the HUD subviews and hides them. ** @param view The view that is going to be searched for HUD subviews.* @param animated If set to YES the HUDs will disappear using the current animationType. If set to NO the HUDs will not use* animations while disappearing.* @return the number of HUDs found and removed.** @see hideHUDForView:animated:* @see animationType*/ + (NSUInteger)hideAllHUDsForView:(UIView *)view animated:(BOOL)animated;/*** Finds the top-most HUD subview and returns it. ** @param view The view that is going to be searched.* @return A reference to the last HUD subview discovered.*/ + (MB_INSTANCETYPE)HUDForView:(UIView *)view;/*** Finds all HUD subviews and returns them.** @param view The view that is going to be searched.* @return All found HUD views (array of MBProgressHUD objects).*/ + (NSArray *)allHUDsForView:(UIView *)view;/*** A convenience constructor that initializes the HUD with the window's bounds. Calls the designated constructor with* window.bounds as the parameter.** @param window The window instance that will provide the bounds for the HUD. Should be the same instance as* the HUD's superview (i.e., the window that the HUD will be added to).*/ - (id)initWithWindow:(UIWindow *)window;/*** A convenience constructor that initializes the HUD with the view's bounds. Calls the designated constructor with* view.bounds as the parameter** @param view The view instance that will provide the bounds for the HUD. Should be the same instance as* the HUD's superview (i.e., the view that the HUD will be added to).*/ - (id)initWithView:(UIView *)view;/** * Display the HUD. You need to make sure that the main thread completes its run loop soon after this method call so* the user interface can be updated. Call this method when your task is already set-up to be executed in a new thread* (e.g., when using something like NSOperation or calling an asynchronous call like NSURLRequest).** @param animated If set to YES the HUD will appear using the current animationType. If set to NO the HUD will not use* animations while appearing.** @see animationType*/ - (void)show:(BOOL)animated;/** * Hide the HUD. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to* hide the HUD when your task completes.** @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use* animations while disappearing.** @see animationType*/ - (void)hide:(BOOL)animated;/** * Hide the HUD after a delay. This still calls the hudWasHidden: delegate. This is the counterpart of the show: method. Use it to* hide the HUD when your task completes.** @param animated If set to YES the HUD will disappear using the current animationType. If set to NO the HUD will not use* animations while disappearing.* @param delay Delay in seconds until the HUD is hidden.** @see animationType*/ - (void)hide:(BOOL)animated afterDelay:(NSTimeInterval)delay;/** * Shows the HUD while a background task is executing in a new thread, then hides the HUD.** This method also takes care of autorelease pools so your method does not have to be concerned with setting up a* pool.** @param method The method to be executed while the HUD is shown. This method will be executed in a new thread.* @param target The object that the target method belongs to.* @param object An optional object to be passed to the method.* @param animated If set to YES the HUD will (dis)appear using the current animationType. If set to NO the HUD will not use* animations while (dis)appearing.*/ - (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated;#if NS_BLOCKS_AVAILABLE/*** Shows the HUD while a block is executing on a background queue, then hides the HUD.** @see showAnimated:whileExecutingBlock:onQueue:completionBlock:*/ - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block;/*** Shows the HUD while a block is executing on a background queue, then hides the HUD.** @see showAnimated:whileExecutingBlock:onQueue:completionBlock:*/ - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block completionBlock:(MBProgressHUDCompletionBlock)completion;/*** Shows the HUD while a block is executing on the specified dispatch queue, then hides the HUD.** @see showAnimated:whileExecutingBlock:onQueue:completionBlock:*/ - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue;/** * Shows the HUD while a block is executing on the specified dispatch queue, executes completion block on the main queue, and then hides the HUD.** @param animated If set to YES the HUD will (dis)appear using the current animationType. If set to NO the HUD will* not use animations while (dis)appearing.* @param block The block to be executed while the HUD is shown.* @param queue The dispatch queue on which the block should be executed.* @param completion The block to be executed on completion.** @see completionBlock*/ - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queuecompletionBlock:(MBProgressHUDCompletionBlock)completion;/*** A block that gets called after the HUD was completely hidden.*/ @property (copy) MBProgressHUDCompletionBlock completionBlock;#endif/** * MBProgressHUD operation mode. The default is MBProgressHUDModeIndeterminate.** @see MBProgressHUDMode*/ @property (assign) MBProgressHUDMode mode;/*** The animation type that should be used when the HUD is shown and hidden. ** @see MBProgressHUDAnimation*/ @property (assign) MBProgressHUDAnimation animationType;/*** The UIView (e.g., a UIImageView) to be shown when the HUD is in MBProgressHUDModeCustomView.* For best results use a 37 by 37 pixel view (so the bounds match the built in indicator bounds). */ @property (MB_STRONG) UIView *customView;/** * The HUD delegate object. ** @see MBProgressHUDDelegate*/ @property (MB_WEAK) id<MBProgressHUDDelegate> delegate;/** * An optional short message to be displayed below the activity indicator. The HUD is automatically resized to fit* the entire text. If the text is too long it will get clipped by displaying "..." at the end. If left unchanged or* set to @"", then no message is displayed.*/ @property (copy) NSString *labelText;/** * An optional details message displayed below the labelText message. This message is displayed only if the labelText* property is also set and is different from an empty string (@""). The details text can span multiple lines. */ @property (copy) NSString *detailsLabelText;/** * The opacity of the HUD window. Defaults to 0.8 (80% opacity). */ @property (assign) float opacity;/*** The color of the HUD window. Defaults to black. If this property is set, color is set using* this UIColor and the opacity property is not used. using retain because performing copy on* UIColor base colors (like [UIColor greenColor]) cause problems with the copyZone.*/ @property (MB_STRONG) UIColor *color;/** * The x-axis offset of the HUD relative to the centre of the superview. */ @property (assign) float xOffset;/** * The y-axis offset of the HUD relative to the centre of the superview. */ @property (assign) float yOffset;/*** The amount of space between the HUD edge and the HUD elements (labels, indicators or custom views). * Defaults to 20.0*/ @property (assign) float margin;/*** The corner radius for the HUD* Defaults to 10.0*/ @property (assign) float cornerRadius;/** * Cover the HUD background view with a radial gradient. */ @property (assign) BOOL dimBackground;/** Grace period is the time (in seconds) that the invoked method may be run without * showing the HUD. If the task finishes before the grace time runs out, the HUD will* not be shown at all. * This may be used to prevent HUD display for very short tasks.* Defaults to 0 (no grace time).* Grace time functionality is only supported when the task status is known!* @see taskInProgress*/ @property (assign) float graceTime;/*** The minimum time (in seconds) that the HUD is shown. * This avoids the problem of the HUD being shown and than instantly hidden.* Defaults to 0 (no minimum show time).*/ @property (assign) float minShowTime;/*** Indicates that the executed operation is in progress. Needed for correct graceTime operation.* If you don't set a graceTime (different than 0.0) this does nothing.* This property is automatically set when using showWhileExecuting:onTarget:withObject:animated:.* When threading is done outside of the HUD (i.e., when the show: and hide: methods are used directly),* you need to set this property when your task starts and completes in order to have normal graceTime * functionality.*/ @property (assign) BOOL taskInProgress;/*** Removes the HUD from its parent view when hidden. * Defaults to NO. */ @property (assign) BOOL removeFromSuperViewOnHide;/** * Font to be used for the main label. Set this property if the default is not adequate. */ @property (MB_STRONG) UIFont* labelFont;/*** Color to be used for the main label. Set this property if the default is not adequate.*/ @property (MB_STRONG) UIColor* labelColor;/*** Font to be used for the details label. Set this property if the default is not adequate.*/ @property (MB_STRONG) UIFont* detailsLabelFont;/** * Color to be used for the details label. Set this property if the default is not adequate.*/ @property (MB_STRONG) UIColor* detailsLabelColor;/*** The color of the activity indicator. Defaults to [UIColor whiteColor]* Does nothing on pre iOS 5.*/ @property (MB_STRONG) UIColor *activityIndicatorColor;/** * The progress of the progress indicator, from 0.0 to 1.0. Defaults to 0.0. */ @property (assign) float progress;/*** The minimum size of the HUD bezel. Defaults to CGSizeZero (no minimum size).*/ @property (assign) CGSize minSize;/*** The actual size of the HUD bezel.* You can use this to limit touch handling on the bezel aria only.* @see https://github.com/jdg/MBProgressHUD/pull/200*/ @property (atomic, assign, readonly) CGSize size;/*** Force the HUD dimensions to be equal if possible. */ @property (assign, getter = isSquare) BOOL square;@end@protocol MBProgressHUDDelegate <NSObject>@optional/** * Called after the HUD was fully hidden from the screen. */ - (void)hudWasHidden:(MBProgressHUD *)hud;@end/*** A progress view for showing definite progress by filling up a circle (pie chart).*/ @interface MBRoundProgressView : UIView /*** Progress (0.0 to 1.0)*/ @property (nonatomic, assign) float progress;/*** Indicator progress color.* Defaults to white [UIColor whiteColor]*/ @property (nonatomic, MB_STRONG) UIColor *progressTintColor;/*** Indicator background (non-progress) color.* Defaults to translucent white (alpha 0.1)*/ @property (nonatomic, MB_STRONG) UIColor *backgroundTintColor;/** Display mode - NO = round or YES = annular. Defaults to round.*/ @property (nonatomic, assign, getter = isAnnular) BOOL annular;@end/*** A flat bar progress view. */ @interface MBBarProgressView : UIView/*** Progress (0.0 to 1.0)*/ @property (nonatomic, assign) float progress;/*** Bar border line color.* Defaults to white [UIColor whiteColor].*/ @property (nonatomic, MB_STRONG) UIColor *lineColor;/*** Bar background color.* Defaults to clear [UIColor clearColor];*/ @property (nonatomic, MB_STRONG) UIColor *progressRemainingColor;/*** Bar progress color.* Defaults to white [UIColor whiteColor].*/ @property (nonatomic, MB_STRONG) UIColor *progressColor;@end
MBProgressHUD.h
![](/assets/blank.gif)
![](/assets/blank.gif)
// // MBProgressHUD.m // Version 0.9 // Created by Matej Bukovinski on 2.4.09. // #import "MBProgressHUD.h" #import <tgmath.h>#if __has_feature(objc_arc)#define MB_AUTORELEASE(exp) exp#define MB_RELEASE(exp) exp#define MB_RETAIN(exp) exp #else#define MB_AUTORELEASE(exp) [exp autorelease]#define MB_RELEASE(exp) [exp release]#define MB_RETAIN(exp) [exp retain] #endif#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000#define MBLabelAlignmentCenter NSTextAlignmentCenter #else#define MBLabelAlignmentCenter UITextAlignmentCenter #endif#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000#define MB_TEXTSIZE(text, font) [text length] > 0 ? [text \sizeWithAttributes:@{NSFontAttributeName:font}] : CGSizeZero; #else#define MB_TEXTSIZE(text, font) [text length] > 0 ? [text sizeWithFont:font] : CGSizeZero; #endif#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000#define MB_MULTILINE_TEXTSIZE(text, font, maxSize, mode) [text length] > 0 ? [text \boundingRectWithSize:maxSize options:(NSStringDrawingUsesLineFragmentOrigin) \attributes:@{NSFontAttributeName:font} context:nil].size : CGSizeZero; #else#define MB_MULTILINE_TEXTSIZE(text, font, maxSize, mode) [text length] > 0 ? [text \sizeWithFont:font constrainedToSize:maxSize lineBreakMode:mode] : CGSizeZero; #endif#ifndef kCFCoreFoundationVersionNumber_iOS_7_0#define kCFCoreFoundationVersionNumber_iOS_7_0 847.20 #endif#ifndef kCFCoreFoundationVersionNumber_iOS_8_0#define kCFCoreFoundationVersionNumber_iOS_8_0 1129.15 #endifstatic const CGFloat kPadding = 4.f; static const CGFloat kLabelFontSize = 16.f; static const CGFloat kDetailsLabelFontSize = 12.f;@interface MBProgressHUD () {BOOL useAnimation;SEL methodForExecution;id targetForExecution;id objectForExecution;UILabel *label;UILabel *detailsLabel;BOOL isFinished;CGAffineTransform rotationTransform; }@property (atomic, MB_STRONG) UIView *indicator; @property (atomic, MB_STRONG) NSTimer *graceTimer; @property (atomic, MB_STRONG) NSTimer *minShowTimer; @property (atomic, MB_STRONG) NSDate *showStarted;@end@implementation MBProgressHUD#pragma mark - Properties@synthesize animationType; @synthesize delegate; @synthesize opacity; @synthesize color; @synthesize labelFont; @synthesize labelColor; @synthesize detailsLabelFont; @synthesize detailsLabelColor; @synthesize indicator; @synthesize xOffset; @synthesize yOffset; @synthesize minSize; @synthesize square; @synthesize margin; @synthesize dimBackground; @synthesize graceTime; @synthesize minShowTime; @synthesize graceTimer; @synthesize minShowTimer; @synthesize taskInProgress; @synthesize removeFromSuperViewOnHide; @synthesize customView; @synthesize showStarted; @synthesize mode; @synthesize labelText; @synthesize detailsLabelText; @synthesize progress; @synthesize size; @synthesize activityIndicatorColor; #if NS_BLOCKS_AVAILABLE @synthesize completionBlock; #endif#pragma mark - Class methods+ (MB_INSTANCETYPE)showHUDAddedTo:(UIView *)view animated:(BOOL)animated {MBProgressHUD *hud = [[self alloc] initWithView:view];hud.removeFromSuperViewOnHide = YES;[view addSubview:hud];[hud show:animated];return MB_AUTORELEASE(hud); }+ (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated {MBProgressHUD *hud = [self HUDForView:view];if (hud != nil) {hud.removeFromSuperViewOnHide = YES;[hud hide:animated];return YES;}return NO; }+ (NSUInteger)hideAllHUDsForView:(UIView *)view animated:(BOOL)animated {NSArray *huds = [MBProgressHUD allHUDsForView:view];for (MBProgressHUD *hud in huds) {hud.removeFromSuperViewOnHide = YES;[hud hide:animated];}return [huds count]; }+ (MB_INSTANCETYPE)HUDForView:(UIView *)view {NSEnumerator *subviewsEnum = [view.subviews reverseObjectEnumerator];for (UIView *subview in subviewsEnum) {if ([subview isKindOfClass:self]) {return (MBProgressHUD *)subview;}}return nil; }+ (NSArray *)allHUDsForView:(UIView *)view {NSMutableArray *huds = [NSMutableArray array];NSArray *subviews = view.subviews;for (UIView *aView in subviews) {if ([aView isKindOfClass:self]) {[huds addObject:aView];}}return [NSArray arrayWithArray:huds]; }#pragma mark - Lifecycle- (id)initWithFrame:(CGRect)frame {self = [super initWithFrame:frame];if (self) {// Set default values for propertiesself.animationType = MBProgressHUDAnimationFade;self.mode = MBProgressHUDModeIndeterminate;self.labelText = nil;self.detailsLabelText = nil;self.opacity = 0.8f;self.color = nil;self.labelFont = [UIFont boldSystemFontOfSize:kLabelFontSize];self.labelColor = [UIColor whiteColor];self.detailsLabelFont = [UIFont boldSystemFontOfSize:kDetailsLabelFontSize];self.detailsLabelColor = [UIColor whiteColor];self.activityIndicatorColor = [UIColor whiteColor];self.xOffset = 0.0f;self.yOffset = 0.0f;self.dimBackground = NO;self.margin = 20.0f;self.cornerRadius = 10.0f;self.graceTime = 0.0f;self.minShowTime = 0.0f;self.removeFromSuperViewOnHide = NO;self.minSize = CGSizeZero;self.square = NO;self.contentMode = UIViewContentModeCenter;self.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin| UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;// Transparent backgroundself.opaque = NO;self.backgroundColor = [UIColor clearColor];// Make it invisible for nowself.alpha = 0.0f;taskInProgress = NO;rotationTransform = CGAffineTransformIdentity;[self setupLabels];[self updateIndicators];[self registerForKVO];[self registerForNotifications];}return self; }- (id)initWithView:(UIView *)view {NSAssert(view, @"View must not be nil.");return [self initWithFrame:view.bounds]; }- (id)initWithWindow:(UIWindow *)window {return [self initWithView:window]; }- (void)dealloc {[self unregisterFromNotifications];[self unregisterFromKVO]; #if !__has_feature(objc_arc)[color release];[indicator release];[label release];[detailsLabel release];[labelText release];[detailsLabelText release];[graceTimer release];[minShowTimer release];[showStarted release];[customView release];[labelFont release];[labelColor release];[detailsLabelFont release];[detailsLabelColor release]; #if NS_BLOCKS_AVAILABLE[completionBlock release]; #endif[super dealloc]; #endif }#pragma mark - Show & hide- (void)show:(BOOL)animated {useAnimation = animated;// If the grace time is set postpone the HUD displayif (self.graceTime > 0.0) {self.graceTimer = [NSTimer scheduledTimerWithTimeInterval:self.graceTime target:self selector:@selector(handleGraceTimer:) userInfo:nil repeats:NO];} // ... otherwise show the HUD imediately else {[self setNeedsDisplay];[self showUsingAnimation:useAnimation];} }- (void)hide:(BOOL)animated {useAnimation = animated;// If the minShow time is set, calculate how long the hud was shown,// and pospone the hiding operation if necessaryif (self.minShowTime > 0.0 && showStarted) {NSTimeInterval interv = [[NSDate date] timeIntervalSinceDate:showStarted];if (interv < self.minShowTime) {self.minShowTimer = [NSTimer scheduledTimerWithTimeInterval:(self.minShowTime - interv) target:self selector:@selector(handleMinShowTimer:) userInfo:nil repeats:NO];return;} }// ... otherwise hide the HUD immediately [self hideUsingAnimation:useAnimation]; }- (void)hide:(BOOL)animated afterDelay:(NSTimeInterval)delay {[self performSelector:@selector(hideDelayed:) withObject:[NSNumber numberWithBool:animated] afterDelay:delay]; }- (void)hideDelayed:(NSNumber *)animated {[self hide:[animated boolValue]]; }#pragma mark - Timer callbacks- (void)handleGraceTimer:(NSTimer *)theTimer {// Show the HUD only if the task is still runningif (taskInProgress) {[self setNeedsDisplay];[self showUsingAnimation:useAnimation];} }- (void)handleMinShowTimer:(NSTimer *)theTimer {[self hideUsingAnimation:useAnimation]; }#pragma mark - View Hierrarchy- (BOOL)shouldPerformOrientationTransform {BOOL isPreiOS8 = NSFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_8_0;// prior to iOS8 code needs to take care of rotation if it is being added to the windowreturn isPreiOS8 && [self.superview isKindOfClass:[UIWindow class]]; }- (void)didMoveToSuperview {if ([self shouldPerformOrientationTransform]) {[self setTransformForCurrentOrientation:NO];} }#pragma mark - Internal show & hide operations- (void)showUsingAnimation:(BOOL)animated {if (animated && animationType == MBProgressHUDAnimationZoomIn) {self.transform = CGAffineTransformConcat(rotationTransform, CGAffineTransformMakeScale(0.5f, 0.5f));} else if (animated && animationType == MBProgressHUDAnimationZoomOut) {self.transform = CGAffineTransformConcat(rotationTransform, CGAffineTransformMakeScale(1.5f, 1.5f));}self.showStarted = [NSDate date];// Fade inif (animated) {[UIView beginAnimations:nil context:NULL];[UIView setAnimationDuration:0.30];self.alpha = 1.0f;if (animationType == MBProgressHUDAnimationZoomIn || animationType == MBProgressHUDAnimationZoomOut) {self.transform = rotationTransform;}[UIView commitAnimations];}else {self.alpha = 1.0f;} }- (void)hideUsingAnimation:(BOOL)animated {// Fade outif (animated && showStarted) {[UIView beginAnimations:nil context:NULL];[UIView setAnimationDuration:0.30];[UIView setAnimationDelegate:self];[UIView setAnimationDidStopSelector:@selector(animationFinished:finished:context:)];// 0.02 prevents the hud from passing through touches during the animation the hud will get completely hidden// in the done methodif (animationType == MBProgressHUDAnimationZoomIn) {self.transform = CGAffineTransformConcat(rotationTransform, CGAffineTransformMakeScale(1.5f, 1.5f));} else if (animationType == MBProgressHUDAnimationZoomOut) {self.transform = CGAffineTransformConcat(rotationTransform, CGAffineTransformMakeScale(0.5f, 0.5f));}self.alpha = 0.02f;[UIView commitAnimations];}else {self.alpha = 0.0f;[self done];}self.showStarted = nil; }- (void)animationFinished:(NSString *)animationID finished:(BOOL)finished context:(void*)context {[self done]; }- (void)done {[NSObject cancelPreviousPerformRequestsWithTarget:self];isFinished = YES;self.alpha = 0.0f;if (removeFromSuperViewOnHide) {[self removeFromSuperview];} #if NS_BLOCKS_AVAILABLEif (self.completionBlock) {self.completionBlock();self.completionBlock = NULL;} #endifif ([delegate respondsToSelector:@selector(hudWasHidden:)]) {[delegate performSelector:@selector(hudWasHidden:) withObject:self];} }#pragma mark - Threading- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated {methodForExecution = method;targetForExecution = MB_RETAIN(target);objectForExecution = MB_RETAIN(object); // Launch execution in new threadself.taskInProgress = YES;[NSThread detachNewThreadSelector:@selector(launchExecution) toTarget:self withObject:nil];// Show HUD view [self show:animated]; }#if NS_BLOCKS_AVAILABLE- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block {dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);[self showAnimated:animated whileExecutingBlock:block onQueue:queue completionBlock:NULL]; }- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block completionBlock:(void (^)())completion {dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);[self showAnimated:animated whileExecutingBlock:block onQueue:queue completionBlock:completion]; }- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue {[self showAnimated:animated whileExecutingBlock:block onQueue:queue completionBlock:NULL]; }- (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queuecompletionBlock:(MBProgressHUDCompletionBlock)completion {self.taskInProgress = YES;self.completionBlock = completion;dispatch_async(queue, ^(void) {block();dispatch_async(dispatch_get_main_queue(), ^(void) {[self cleanUp];});});[self show:animated]; }#endif- (void)launchExecution {@autoreleasepool { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks"// Start executing the requested task [targetForExecution performSelector:methodForExecution withObject:objectForExecution]; #pragma clang diagnostic pop// Task completed, update view in main thread (note: view operations should// be done only in the main thread) [self performSelectorOnMainThread:@selector(cleanUp) withObject:nil waitUntilDone:NO];} }- (void)cleanUp {taskInProgress = NO; #if !__has_feature(objc_arc)[targetForExecution release];[objectForExecution release]; #elsetargetForExecution = nil;objectForExecution = nil; #endif[self hide:useAnimation]; }#pragma mark - UI- (void)setupLabels {label = [[UILabel alloc] initWithFrame:self.bounds];label.adjustsFontSizeToFitWidth = NO;label.textAlignment = MBLabelAlignmentCenter;label.opaque = NO;label.backgroundColor = [UIColor clearColor];label.textColor = self.labelColor;label.font = self.labelFont;label.text = self.labelText;[self addSubview:label];detailsLabel = [[UILabel alloc] initWithFrame:self.bounds];detailsLabel.font = self.detailsLabelFont;detailsLabel.adjustsFontSizeToFitWidth = NO;detailsLabel.textAlignment = MBLabelAlignmentCenter;detailsLabel.opaque = NO;detailsLabel.backgroundColor = [UIColor clearColor];detailsLabel.textColor = self.detailsLabelColor;detailsLabel.numberOfLines = 0;detailsLabel.font = self.detailsLabelFont;detailsLabel.text = self.detailsLabelText;[self addSubview:detailsLabel]; }- (void)updateIndicators {BOOL isActivityIndicator = [indicator isKindOfClass:[UIActivityIndicatorView class]];BOOL isRoundIndicator = [indicator isKindOfClass:[MBRoundProgressView class]];if (mode == MBProgressHUDModeIndeterminate) {if (!isActivityIndicator) {// Update to indeterminate indicator [indicator removeFromSuperview];self.indicator = MB_AUTORELEASE([[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]);[(UIActivityIndicatorView *)indicator startAnimating];[self addSubview:indicator];} #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000[(UIActivityIndicatorView *)indicator setColor:self.activityIndicatorColor]; #endif}else if (mode == MBProgressHUDModeDeterminateHorizontalBar) {// Update to bar determinate indicator [indicator removeFromSuperview];self.indicator = MB_AUTORELEASE([[MBBarProgressView alloc] init]);[self addSubview:indicator];}else if (mode == MBProgressHUDModeDeterminate || mode == MBProgressHUDModeAnnularDeterminate) {if (!isRoundIndicator) {// Update to determinante indicator [indicator removeFromSuperview];self.indicator = MB_AUTORELEASE([[MBRoundProgressView alloc] init]);[self addSubview:indicator];}if (mode == MBProgressHUDModeAnnularDeterminate) {[(MBRoundProgressView *)indicator setAnnular:YES];}} else if (mode == MBProgressHUDModeCustomView && customView != indicator) {// Update custom view indicator [indicator removeFromSuperview];self.indicator = customView;[self addSubview:indicator];} else if (mode == MBProgressHUDModeText) {[indicator removeFromSuperview];self.indicator = nil;} }#pragma mark - Layout- (void)layoutSubviews {[super layoutSubviews];// Entirely cover the parent viewUIView *parent = self.superview;if (parent) {self.frame = parent.bounds;}CGRect bounds = self.bounds;// Determine the total width and height neededCGFloat maxWidth = CGRectGetWidth(bounds) - 4 * margin;CGSize totalSize = CGSizeZero;CGRect indicatorF = indicator.bounds;indicatorF.size.width = MIN(CGRectGetWidth(indicatorF), maxWidth);totalSize.width = MAX(totalSize.width, CGRectGetWidth(indicatorF));totalSize.height += CGRectGetHeight(indicatorF);CGSize labelSize = MB_TEXTSIZE(label.text, label.font);labelSize.width = MIN(labelSize.width, maxWidth);totalSize.width = MAX(totalSize.width, labelSize.width);totalSize.height += labelSize.height;if (labelSize.height > 0.f && CGRectGetHeight(indicatorF) > 0.f) {totalSize.height += kPadding;}CGFloat remainingHeight = CGRectGetHeight(bounds) - totalSize.height - kPadding - 4 * margin;CGSize maxSize = CGSizeMake(maxWidth, remainingHeight);CGSize detailsLabelSize = MB_MULTILINE_TEXTSIZE(detailsLabel.text, detailsLabel.font, maxSize, detailsLabel.lineBreakMode);totalSize.width = MAX(totalSize.width, detailsLabelSize.width);totalSize.height += detailsLabelSize.height;if (detailsLabelSize.height > 0.f && (indicatorF.size.height > 0.f || labelSize.height > 0.f)) {totalSize.height += kPadding;}totalSize.width += 2 * margin;totalSize.height += 2 * margin;// Position elementsCGFloat yPos = round(((CGRectGetHeight(bounds) - totalSize.height) / 2)) + margin + yOffset;CGFloat xPos = xOffset;indicatorF.origin.y = yPos;indicatorF.origin.x = round((CGRectGetWidth(bounds) - CGRectGetWidth(indicatorF)) / 2) + xPos;indicator.frame = indicatorF;yPos += CGRectGetHeight(indicatorF);if (labelSize.height > 0.f && CGRectGetHeight(indicatorF) > 0.f) {yPos += kPadding;}CGRect labelF;labelF.origin.y = yPos;labelF.origin.x = round((CGRectGetWidth(bounds) - labelSize.width) / 2) + xPos;labelF.size = labelSize;label.frame = labelF;yPos += labelF.size.height;if (detailsLabelSize.height > 0.f && (CGRectGetHeight(indicatorF) > 0.f || labelSize.height > 0.f)) {yPos += kPadding;}CGRect detailsLabelF;detailsLabelF.origin.y = yPos;detailsLabelF.origin.x = round((CGRectGetWidth(bounds) - detailsLabelSize.width) / 2) + xPos;detailsLabelF.size = detailsLabelSize;detailsLabel.frame = detailsLabelF;// Enforce minsize and quare rulesif (square) {CGFloat max = MAX(totalSize.width, totalSize.height);if (max <= bounds.size.width - 2 * margin) {totalSize.width = max;}if (max <= bounds.size.height - 2 * margin) {totalSize.height = max;}}if (totalSize.width < minSize.width) {totalSize.width = minSize.width;} if (totalSize.height < minSize.height) {totalSize.height = minSize.height;}size = totalSize; }#pragma mark BG Drawing- (void)drawRect:(CGRect)rect {CGContextRef context = UIGraphicsGetCurrentContext();UIGraphicsPushContext(context);if (self.dimBackground) {//Gradient colourssize_t gradLocationsNum = 2;CGFloat gradLocations[2] = {0.0f, 1.0f};CGFloat gradColors[8] = {0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.75f}; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, gradColors, gradLocations, gradLocationsNum);CGColorSpaceRelease(colorSpace);//Gradient centerCGPoint gradCenter= CGPointMake(CGRectGetWidth(self.bounds)/2, CGRectGetHeight(self.bounds)/2);//Gradient radiusfloat gradRadius = MIN(CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)) ;//Gradient draw CGContextDrawRadialGradient (context, gradient, gradCenter,0, gradCenter, gradRadius,kCGGradientDrawsAfterEndLocation);CGGradientRelease(gradient);}// Set background rect colorif (self.color) {CGContextSetFillColorWithColor(context, self.color.CGColor);} else {CGContextSetGrayFillColor(context, 0.0f, self.opacity);}// Center HUDCGRect allRect = self.bounds;// Draw rounded HUD backgroud rectCGRect boxRect = CGRectMake(round((CGRectGetWidth(allRect) - size.width) / 2) + self.xOffset,round((CGRectGetHeight(allRect) - size.height) / 2) + self.yOffset, size.width, size.height);float radius = self.cornerRadius;CGContextBeginPath(context);CGContextMoveToPoint(context, CGRectGetMinX(boxRect) + radius, CGRectGetMinY(boxRect));CGContextAddArc(context, CGRectGetMaxX(boxRect) - radius, CGRectGetMinY(boxRect) + radius, radius, 3 * (float)M_PI / 2, 0, 0);CGContextAddArc(context, CGRectGetMaxX(boxRect) - radius, CGRectGetMaxY(boxRect) - radius, radius, 0, (float)M_PI / 2, 0);CGContextAddArc(context, CGRectGetMinX(boxRect) + radius, CGRectGetMaxY(boxRect) - radius, radius, (float)M_PI / 2, (float)M_PI, 0);CGContextAddArc(context, CGRectGetMinX(boxRect) + radius, CGRectGetMinY(boxRect) + radius, radius, (float)M_PI, 3 * (float)M_PI / 2, 0);CGContextClosePath(context);CGContextFillPath(context);UIGraphicsPopContext(); }#pragma mark - KVO- (void)registerForKVO {for (NSString *keyPath in [self observableKeypaths]) {[self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:NULL];} }- (void)unregisterFromKVO {for (NSString *keyPath in [self observableKeypaths]) {[self removeObserver:self forKeyPath:keyPath];} }- (NSArray *)observableKeypaths {return [NSArray arrayWithObjects:@"mode", @"customView", @"labelText", @"labelFont", @"labelColor",@"detailsLabelText", @"detailsLabelFont", @"detailsLabelColor", @"progress", @"activityIndicatorColor", nil]; }- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {if (![NSThread isMainThread]) {[self performSelectorOnMainThread:@selector(updateUIForKeypath:) withObject:keyPath waitUntilDone:NO];} else {[self updateUIForKeypath:keyPath];} }- (void)updateUIForKeypath:(NSString *)keyPath {if ([keyPath isEqualToString:@"mode"] || [keyPath isEqualToString:@"customView"] ||[keyPath isEqualToString:@"activityIndicatorColor"]) {[self updateIndicators];} else if ([keyPath isEqualToString:@"labelText"]) {label.text = self.labelText;} else if ([keyPath isEqualToString:@"labelFont"]) {label.font = self.labelFont;} else if ([keyPath isEqualToString:@"labelColor"]) {label.textColor = self.labelColor;} else if ([keyPath isEqualToString:@"detailsLabelText"]) {detailsLabel.text = self.detailsLabelText;} else if ([keyPath isEqualToString:@"detailsLabelFont"]) {detailsLabel.font = self.detailsLabelFont;} else if ([keyPath isEqualToString:@"detailsLabelColor"]) {detailsLabel.textColor = self.detailsLabelColor;} else if ([keyPath isEqualToString:@"progress"]) {if ([indicator respondsToSelector:@selector(setProgress:)]) {[(id)indicator setValue:@(progress) forKey:@"progress"];}return;}[self setNeedsLayout];[self setNeedsDisplay]; }#pragma mark - Notifications- (void)registerForNotifications {NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];[nc addObserver:self selector:@selector(statusBarOrientationDidChange:)name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; }- (void)unregisterFromNotifications {NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];[nc removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; }- (void)statusBarOrientationDidChange:(NSNotification *)notification {UIView *superview = self.superview;if (!superview) {return;} else if ([self shouldPerformOrientationTransform]) {[self setTransformForCurrentOrientation:YES];} else {self.frame = self.superview.bounds;[self setNeedsDisplay];} }- (void)setTransformForCurrentOrientation:(BOOL)animated {// Stay in sync with the superviewif (self.superview) {self.bounds = self.superview.bounds;[self setNeedsDisplay];}// Window coordinates differ below iOS8// In iOS8 the UIScreen's bounds now interface-oriented// more see https://developer.apple.com/videos/wwdc/2014/#214CGFloat radians = 0;if (NSFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_8_0) {UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;if (UIInterfaceOrientationIsLandscape(orientation)) {if (orientation == UIInterfaceOrientationLandscapeLeft) {radians = -(CGFloat)M_PI_2;} else {radians = (CGFloat)M_PI_2;}self.bounds = CGRectMake(0, 0, CGRectGetHeight(self.bounds), CGRectGetWidth(self.bounds));} else {if (orientation == UIInterfaceOrientationPortraitUpsideDown) {radians = (CGFloat)M_PI;} else {radians = 0;}}}rotationTransform = CGAffineTransformMakeRotation(radians);if (animated) {[UIView beginAnimations:nil context:nil];[UIView setAnimationDuration:0.3];}[self setTransform:rotationTransform];if (animated) {[UIView commitAnimations];} }@end@implementation MBRoundProgressView#pragma mark - Lifecycle- (id)init {return [self initWithFrame:CGRectMake(0.f, 0.f, 37.f, 37.f)]; }- (id)initWithFrame:(CGRect)frame {self = [super initWithFrame:frame];if (self) {self.backgroundColor = [UIColor clearColor];self.opaque = NO;_progress = 0.f;_annular = NO;_progressTintColor = [[UIColor alloc] initWithWhite:1.f alpha:1.f];_backgroundTintColor = [[UIColor alloc] initWithWhite:1.f alpha:.1f];[self registerForKVO];}return self; }- (void)dealloc {[self unregisterFromKVO]; #if !__has_feature(objc_arc)[_progressTintColor release];[_backgroundTintColor release];[super dealloc]; #endif }#pragma mark - Drawing- (void)drawRect:(CGRect)rect {CGRect allRect = self.bounds;CGRect circleRect = CGRectInset(allRect, 2.0f, 2.0f);CGContextRef context = UIGraphicsGetCurrentContext();if (_annular) {// Draw backgroundBOOL isPreiOS7 = NSFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_7_0;CGFloat lineWidth = isPreiOS7 ? 5.f : 2.f;UIBezierPath *processBackgroundPath = [UIBezierPath bezierPath];processBackgroundPath.lineWidth = lineWidth;processBackgroundPath.lineCapStyle = kCGLineCapButt;CGPoint center = CGPointMake(CGRectGetWidth(self.bounds)/2, CGRectGetHeight(self.bounds)/2);CGFloat radius = (CGRectGetWidth(self.bounds) - lineWidth)/2;CGFloat startAngle = - ((float)M_PI / 2); // 90 degreesCGFloat endAngle = (2 * (float)M_PI) + startAngle;[processBackgroundPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES];[_backgroundTintColor set];[processBackgroundPath stroke];// Draw progressUIBezierPath *processPath = [UIBezierPath bezierPath];processPath.lineCapStyle = isPreiOS7 ? kCGLineCapRound : kCGLineCapSquare;processPath.lineWidth = lineWidth;endAngle = (self.progress * 2 * (float)M_PI) + startAngle;[processPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES];[_progressTintColor set];[processPath stroke];} else {// Draw background [_progressTintColor setStroke];[_backgroundTintColor setFill];CGContextSetLineWidth(context, 2.0f);CGContextFillEllipseInRect(context, circleRect);CGContextStrokeEllipseInRect(context, circleRect);// Draw progressCGPoint center = CGPointMake(CGRectGetWidth(allRect) / 2, CGRectGetHeight(allRect) / 2);CGFloat radius = (CGRectGetWidth(allRect) - 4) / 2;CGFloat startAngle = - ((float)M_PI / 2); // 90 degreesCGFloat endAngle = (self.progress * 2 * (float)M_PI) + startAngle;CGContextSetRGBFillColor(context, 1.0f, 1.0f, 1.0f, 1.0f); // white CGContextMoveToPoint(context, center.x, center.y);CGContextAddArc(context, center.x, center.y, radius, startAngle, endAngle, 0);CGContextClosePath(context);CGContextFillPath(context);} }#pragma mark - KVO- (void)registerForKVO {for (NSString *keyPath in [self observableKeypaths]) {[self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:NULL];} }- (void)unregisterFromKVO {for (NSString *keyPath in [self observableKeypaths]) {[self removeObserver:self forKeyPath:keyPath];} }- (NSArray *)observableKeypaths {return [NSArray arrayWithObjects:@"progressTintColor", @"backgroundTintColor", @"progress", @"annular", nil]; }- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {[self setNeedsDisplay]; }@end@implementation MBBarProgressView#pragma mark - Lifecycle- (id)init {return [self initWithFrame:CGRectMake(.0f, .0f, 120.0f, 20.0f)]; }- (id)initWithFrame:(CGRect)frame {self = [super initWithFrame:frame];if (self) {_progress = 0.f;_lineColor = [UIColor whiteColor];_progressColor = [UIColor whiteColor];_progressRemainingColor = [UIColor clearColor];self.backgroundColor = [UIColor clearColor];self.opaque = NO;[self registerForKVO];}return self; }- (void)dealloc {[self unregisterFromKVO]; #if !__has_feature(objc_arc)[_lineColor release];[_progressColor release];[_progressRemainingColor release];[super dealloc]; #endif }#pragma mark - Drawing- (void)drawRect:(CGRect)rect {CGContextRef context = UIGraphicsGetCurrentContext();CGContextSetLineWidth(context, 2);CGContextSetStrokeColorWithColor(context,[_lineColor CGColor]);CGContextSetFillColorWithColor(context, [_progressRemainingColor CGColor]);// Draw backgroundfloat radius = (CGRectGetHeight(rect) / 2) - 2;CGContextMoveToPoint(context, 2, CGRectGetHeight(rect)/2);CGContextAddArcToPoint(context, 2, 2, radius + 2, 2, radius);CGContextAddLineToPoint(context, CGRectGetWidth(rect) - radius - 2, 2);CGContextAddArcToPoint(context, CGRectGetWidth(rect) - 2, 2, CGRectGetWidth(rect) - 2, CGRectGetHeight(rect) / 2, radius);CGContextAddArcToPoint(context, CGRectGetWidth(rect) - 2, CGRectGetHeight(rect) - 2, CGRectGetWidth(rect) - radius - 2, CGRectGetHeight(rect) - 2, radius);CGContextAddLineToPoint(context, radius + 2, CGRectGetHeight(rect) - 2);CGContextAddArcToPoint(context, 2, CGRectGetHeight(rect) - 2, 2, CGRectGetHeight(rect)/2, radius);CGContextFillPath(context);// Draw borderCGContextMoveToPoint(context, 2, CGRectGetHeight(rect)/2);CGContextAddArcToPoint(context, 2, 2, radius + 2, 2, radius);CGContextAddLineToPoint(context, CGRectGetWidth(rect) - radius - 2, 2);CGContextAddArcToPoint(context, CGRectGetWidth(rect) - 2, 2, CGRectGetWidth(rect) - 2, CGRectGetHeight(rect) / 2, radius);CGContextAddArcToPoint(context, CGRectGetWidth(rect) - 2, CGRectGetHeight(rect) - 2, CGRectGetWidth(rect) - radius - 2, CGRectGetHeight(rect) - 2, radius);CGContextAddLineToPoint(context, radius + 2, CGRectGetHeight(rect) - 2);CGContextAddArcToPoint(context, 2, CGRectGetHeight(rect) - 2, 2, CGRectGetHeight(rect)/2, radius);CGContextStrokePath(context);CGContextSetFillColorWithColor(context, [_progressColor CGColor]);radius = radius - 2;float amount = self.progress * CGRectGetWidth(rect);// Progress in the middle areaif (amount >= radius + 4 && amount <= (CGRectGetWidth(rect) - radius - 4)) {CGContextMoveToPoint(context, 4, CGRectGetHeight(rect)/2);CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius);CGContextAddLineToPoint(context, amount, 4);CGContextAddLineToPoint(context, amount, radius + 4);CGContextMoveToPoint(context, 4, CGRectGetHeight(rect)/2);CGContextAddArcToPoint(context, 4, CGRectGetHeight(rect) - 4, radius + 4, CGRectGetHeight(rect) - 4, radius);CGContextAddLineToPoint(context, amount, CGRectGetHeight(rect) - 4);CGContextAddLineToPoint(context, amount, radius + 4);CGContextFillPath(context);}// Progress in the right arcelse if (amount > radius + 4) {float x = amount - (CGRectGetWidth(rect) - radius - 4);CGContextMoveToPoint(context, 4, CGRectGetHeight(rect)/2);CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius);CGContextAddLineToPoint(context, CGRectGetWidth(rect) - radius - 4, 4);float angle = -acos(x/radius);if (isnan(angle)) angle = 0;CGContextAddArc(context, CGRectGetWidth(rect) - radius - 4, CGRectGetHeight(rect)/2, radius, M_PI, angle, 0);CGContextAddLineToPoint(context, amount, CGRectGetHeight(rect)/2);CGContextMoveToPoint(context, 4, CGRectGetHeight(rect)/2);CGContextAddArcToPoint(context, 4, CGRectGetHeight(rect) - 4, radius + 4, CGRectGetHeight(rect) - 4, radius);CGContextAddLineToPoint(context, CGRectGetWidth(rect) - radius - 4, CGRectGetHeight(rect) - 4);angle = acos(x/radius);if (isnan(angle)) angle = 0;CGContextAddArc(context, CGRectGetWidth(rect) - radius - 4, CGRectGetHeight(rect)/2, radius, -M_PI, angle, 1);CGContextAddLineToPoint(context, amount, CGRectGetHeight(rect)/2);CGContextFillPath(context);}// Progress is in the left arcelse if (amount < radius + 4 && amount > 0) {CGContextMoveToPoint(context, 4, CGRectGetHeight(rect)/2);CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius);CGContextAddLineToPoint(context, radius + 4, CGRectGetHeight(rect)/2);CGContextMoveToPoint(context, 4, CGRectGetHeight(rect)/2);CGContextAddArcToPoint(context, 4, CGRectGetHeight(rect) - 4, radius + 4, CGRectGetHeight(rect) - 4, radius);CGContextAddLineToPoint(context, radius + 4, CGRectGetHeight(rect)/2);CGContextFillPath(context);} }#pragma mark - KVO- (void)registerForKVO {for (NSString *keyPath in [self observableKeypaths]) {[self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:NULL];} }- (void)unregisterFromKVO {for (NSString *keyPath in [self observableKeypaths]) {[self removeObserver:self forKeyPath:keyPath];} }- (NSArray *)observableKeypaths {return [NSArray arrayWithObjects:@"lineColor", @"progressRemainingColor", @"progressColor", @"progress", nil]; }- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {[self setNeedsDisplay]; }@end
MBProgressHUD.m
以下是本人在MBProgressHUD基础上封装的类,觉得部分的使用基于block
ShowHUD.h 与 ShowHUD.m
// // ShowHUD.h // TestHUD // // Created by YouXianMing on 14-9-29. // Copyright (c) 2014年 YouXianMing. All rights reserved. // #import <Foundation/Foundation.h> #import "MBProgressHUD.h" @class ShowHUD;// 定义block typedef void (^ConfigShowHUDBlock)(ShowHUD *config); typedef UIView *(^ConfigShowHUDCustomViewBlock)();// 定义枚举值 typedef enum {Fade = MBProgressHUDAnimationFade,Zoom = MBProgressHUDAnimationZoom,ZoomOut = MBProgressHUDAnimationZoomOut,ZoomIn = MBProgressHUDAnimationZoomIn, } HUDAnimationType;@interface ShowHUD : NSObject// 动画效果 @property (nonatomic, assign) HUDAnimationType animationStyle; // 动画样式// 文本加菊花 @property (nonatomic, strong) NSString *text; // 文本 @property (nonatomic, strong) UIFont *textFont; // 文本字体// 自定义view @property (nonatomic, strong) UIView *customView; // 自定义view 37x37尺寸// 只显示文本的相关设置 @property (nonatomic, assign) BOOL showTextOnly; // 只显示文本// 边缘留白 @property (nonatomic, assign) float margin; // 边缘留白// 颜色设置(设置了颜色之后,透明度就会失效) @property (nonatomic, strong) UIColor *backgroundColor; // 背景颜色 @property (nonatomic, strong) UIColor *labelColor; // 文本颜色// 透明度 @property (nonatomic, assign) float opacity; // 透明度// 圆角 @property (nonatomic, assign) float cornerRadius; // 圆角// 仅仅显示文本并持续几秒的方法 /* - 使用示例 -[ShowHUD showTextOnly:@"请稍后,显示不了..."configParameter:^(ShowHUD *config) {config.margin = 10.f; // 边缘留白config.opacity = 0.7f; // 设定透明度config.cornerRadius = 2.f; // 设定圆角} duration:3 inView:self.view];*/ + (void)showTextOnly:(NSString *)textconfigParameter:(ConfigShowHUDBlock)configduration:(NSTimeInterval)secinView:(UIView *)view;// 显示文本与菊花并持续几秒的方法(文本为nil时只显示菊花) /* - 使用示例 -[ShowHUD showText:@"请稍后,显示不了..."configParameter:^(ShowHUD *config) {config.margin = 10.f; // 边缘留白config.opacity = 0.7f; // 设定透明度config.cornerRadius = 2.f; // 设定圆角} duration:3 inView:self.view];*/ + (void)showText:(NSString *)textconfigParameter:(ConfigShowHUDBlock)configduration:(NSTimeInterval)secinView:(UIView *)view;// 加载自定义view并持续几秒的方法 /* - 使用示例 -[ShowHUD showText:@"请稍后,显示不了..."configParameter:^(ShowHUD *config) {config.margin = 10.f; // 边缘留白config.opacity = 0.7f; // 设定透明度config.cornerRadius = 2.f; // 设定圆角} duration:3 inView:self.view];*/ + (void)showCustomView:(ConfigShowHUDCustomViewBlock)viewBlockconfigParameter:(ConfigShowHUDBlock)configduration:(NSTimeInterval)secinView:(UIView *)view;+ (instancetype)showTextOnly:(NSString *)textconfigParameter:(ConfigShowHUDBlock)configinView:(UIView *)view; + (instancetype)showText:(NSString *)textconfigParameter:(ConfigShowHUDBlock)configinView:(UIView *)view; + (instancetype)showCustomView:(ConfigShowHUDCustomViewBlock)viewBlockconfigParameter:(ConfigShowHUDBlock)configinView:(UIView *)view; - (void)hide;@end
// // ShowHUD.m // TestHUD // // Created by YouXianMing on 14-9-29. // Copyright (c) 2014年 YouXianMing. All rights reserved. // #import "ShowHUD.h"#ifdef DEBUG #define ShowHUD_DLog(fmt, ...) NSLog((@"ShowHUD.m:%s:%d" fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); #else #define ShowHUD_DLog(...) #endif@interface ShowHUD ()<MBProgressHUDDelegate>{MBProgressHUD *_hud; }@end@implementation ShowHUD- (instancetype)initWithView:(UIView *)view {if (view == nil) {return nil;}self = [super init];if (self) {_hud = [[MBProgressHUD alloc] initWithView:view];_hud.delegate = self; // 设置代理_hud.animationType = MBProgressHUDAnimationZoom; // 默认动画样式_hud.removeFromSuperViewOnHide = YES; // 该视图隐藏后则自动从父视图移除掉 [view addSubview:_hud];}return self; }- (void)hide:(BOOL)hide afterDelay:(NSTimeInterval)delay {[_hud hide:hide afterDelay:delay]; }- (void)hide {[_hud hide:YES]; }- (void)show:(BOOL)show {// 根据属性判断是否要显示文本if (_text != nil && _text.length != 0) {_hud.labelText = _text;}// 设置文本字体if (_textFont) {_hud.labelFont = _textFont;}// 如果设置这个属性,则只显示文本if (_showTextOnly == YES && _text != nil && _text.length != 0) {_hud.mode = MBProgressHUDModeText;}// 设置背景色if (_backgroundColor) {_hud.color = _backgroundColor;}// 文本颜色if (_labelColor) {_hud.labelColor = _labelColor;}// 设置圆角if (_cornerRadius) {_hud.cornerRadius = _cornerRadius;}// 设置透明度if (_opacity) {_hud.opacity = _opacity;}// 自定义viewif (_customView) {_hud.mode = MBProgressHUDModeCustomView;_hud.customView = _customView;}// 边缘留白if (_margin > 0) {_hud.margin = _margin;}[_hud show:show]; }#pragma mark - HUD代理方法 - (void)hudWasHidden:(MBProgressHUD *)hud {[_hud removeFromSuperview];_hud = nil; }#pragma mark - 重写setter方法 @synthesize animationStyle = _animationStyle; - (void)setAnimationStyle:(HUDAnimationType)animationStyle {_animationStyle = animationStyle;_hud.animationType = (MBProgressHUDAnimation)_animationStyle; } - (HUDAnimationType)animationStyle {return _animationStyle; }#pragma mark - 便利的方法 + (void)showTextOnly:(NSString *)textconfigParameter:(ConfigShowHUDBlock)configduration:(NSTimeInterval)secinView:(UIView *)view {ShowHUD *hud = [[ShowHUD alloc] initWithView:view];hud.text = text;hud.showTextOnly = YES;hud.margin = 10.f;// 配置额外的参数 config(hud);// 显示 [hud show:YES];// 延迟sec后消失 [hud hide:YES afterDelay:sec]; }+ (void)showText:(NSString *)textconfigParameter:(ConfigShowHUDBlock)configduration:(NSTimeInterval)secinView:(UIView *)view {ShowHUD *hud = [[ShowHUD alloc] initWithView:view];hud.text = text;hud.margin = 10.f;// 配置额外的参数 config(hud);// 显示 [hud show:YES];// 延迟sec后消失 [hud hide:YES afterDelay:sec]; }+ (void)showCustomView:(ConfigShowHUDCustomViewBlock)viewBlockconfigParameter:(ConfigShowHUDBlock)configduration:(NSTimeInterval)secinView:(UIView *)view {ShowHUD *hud = [[ShowHUD alloc] initWithView:view];hud.margin = 10.f;// 配置额外的参数 config(hud);// 自定义Viewhud.customView = viewBlock();// 显示 [hud show:YES];[hud hide:YES afterDelay:sec]; }+ (instancetype)showTextOnly:(NSString *)textconfigParameter:(ConfigShowHUDBlock)configinView:(UIView *)view {ShowHUD *hud = [[ShowHUD alloc] initWithView:view];hud.text = text;hud.showTextOnly = YES;hud.margin = 10.f;// 配置额外的参数 config(hud);// 显示 [hud show:YES];return hud; }+ (instancetype)showText:(NSString *)textconfigParameter:(ConfigShowHUDBlock)configinView:(UIView *)view {ShowHUD *hud = [[ShowHUD alloc] initWithView:view];hud.text = text;hud.margin = 10.f;// 配置额外的参数 config(hud);// 显示 [hud show:YES];return hud; }+ (instancetype)showCustomView:(ConfigShowHUDCustomViewBlock)viewBlockconfigParameter:(ConfigShowHUDBlock)configinView:(UIView *)view {ShowHUD *hud = [[ShowHUD alloc] initWithView:view];hud.margin = 10.f;// 配置额外的参数 config(hud);// 自定义Viewhud.customView = viewBlock();// 显示 [hud show:YES];return hud; }- (void)dealloc {ShowHUD_DLog(@"资源释放了,没有泄露^_^"); }@end
使用时候的源码如下:
// // ViewController.m // TestHUD // // Created by YouXianMing on 14-9-29. // Copyright (c) 2014年 YouXianMing. All rights reserved. // #import "ViewController.h" #import "ShowHUD.h" // 引入头文件 typedef enum : NSUInteger {CASE_1, // 显示文本和菊花,延时3秒后消失CASE_2, // 仅仅显示文本,延时3秒后消失CASE_3, // 加载自定义view,3秒后消失 } E_CASE;@interface ViewController ()<MBProgressHUDDelegate>@property (nonatomic, assign) NSInteger caseType;@end@implementation ViewController- (void)showHUD {UIWindow *window = [UIApplication sharedApplication].keyWindow;switch (_caseType++ % 3) {case CASE_1: {[ShowHUD showText:@"YouXianMing"configParameter:^(ShowHUD *config) {config.margin = 10.f; // 边缘留白config.opacity = 0.7f; // 设定透明度config.cornerRadius = 1.f; // 设定圆角config.textFont = [UIFont systemFontOfSize:11.f];} duration:3 inView:window];} break;case CASE_2: {[ShowHUD showTextOnly:@"YouXianMing"configParameter:^(ShowHUD *config) {config.animationStyle = ZoomOut; // 设置动画方式config.margin = 20.f; // 边缘留白config.opacity = 0.8f; // 设定透明度config.cornerRadius = 0.1f; // 设定圆角config.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.8]; // 设置背景色config.labelColor = [[UIColor whiteColor] colorWithAlphaComponent:1.0];// 设置文本颜色} duration:3 inView:window];} break;// case CASE_3: { // BackgroundView *backView = [[BackgroundView alloc] initInView:window]; // backView.startDuration = 0.25; // backView.endDuration = 0.25; // [backView addToView]; // // ShowHUD *hud = [ShowHUD showCustomView:^UIView *{ // // 返回一个自定义view即可,hud会自动根据你返回的view调整空间 // MulticolorView *showView = [[MulticolorView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)]; // showView.lineWidth = 1.f; // showView.sec = 1.5f; // showView.colors = @[(id)[UIColor cyanColor].CGColor, // (id)[UIColor yellowColor].CGColor, // (id)[UIColor cyanColor].CGColor]; // [showView startAnimation]; // return showView; // } configParameter:^(ShowHUD *config) { // config.animationStyle = Zoom; // 设定动画方式 // config.margin = 10.f; // 边缘留白 // config.cornerRadius = 2.f; // 边缘圆角 // config.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4f]; // } inView:window]; // // // 延迟5秒后消失 // [GCDQueue executeInMainQueue:^{ // [hud hide]; // [backView removeSelf]; // } afterDelaySecs:5]; // } break;default:break;} }- (void)viewDidLoad {[super viewDidLoad];_caseType = 0;UIButton *button = [[UIButton alloc] initWithFrame:self.view.bounds];[self.view addSubview:button];[button addTarget:selfaction:@selector(buttonEvent:)forControlEvents:UIControlEventTouchUpInside]; }- (void)buttonEvent:(id)sender {[self showHUD]; }@end
以下是使用上的一些小细节
转载于:https://www.cnblogs.com/YouXianMing/p/4003815.html
对MBProgressHUD进行二次封装并精简使用相关推荐
- 基于 POI 封装 ExcelUtil 精简的 Excel 导入导出
由于 poi 本身只是针对于 excel 等office软件的一个工具包,在一些常规的 excel 导入导出时,还需要再做一次精简的封装,简化代码耦合. 一.现状 本人经历过几家公司的代码封装,导入导 ...
- win10二次封装解决办法
win10封装使用EasySysprep4.5 因为采用的母盘是封装好的系统再次封装会出现问题 在准备工作做好后启动EasySysprep首次封装会报错 报错的log在C:\Windows\Syste ...
- Glide二次封装库的使用
更多代码可以查询本人GitHub:欢迎阅读,star点起来. Glide二次封装库源码 前言 为什么选择Glide? Glide 轻量级 速度快 可以根据所需加载图片的大小自动适配所需分辨率的图 支 ...
- 高德地图markevents_GitHub - mingxuWang/Map: 高德地图API二次封装
Map组件设计文档 组件设计目的 分析当前各业务方向(销售端.商城.数据可视化.TMS)内地图相关应用的地图功能使用情况,封装Map组件供给各业务向进行使用. 将高德地图API进行二次封装,降低地图相 ...
- Android 应用程序集成Google 登录及二次封装
谷歌登录API: https://developers.google.com/identity/sign-in/android/ 1.注册并且登录google网站 https://accounts. ...
- vue全家桶 ---axios的使用和二次封装
1.前提基础 本文在vue项目搭建的基础上,vue-router路由配置的基础上,对vue项目中axios的使用进行介绍. 2.axios的使用以及拦截器的设置. 安装axios cnpm i axi ...
- iOS安全之二次封装AFN并设置请求头/执行HTTPS加强安全
以前都是直接复制粘贴二次封装好的代码 , 现在都忘了怎么写 . 恰好当前项目要用到请求头 , 在网上学习了一下 , 统一敲了一遍 .自从到了现在公司 , 才发现要学的东西太多了 , 当然 , 有个好的 ...
- java二次封装_基于OKhttp+Rxjava2+Retrofit进行二次封装
概述 基于Retrofit进行二次封装,优雅的初始化设置.基于Okhttp拦截器和基础缓存,封装了无网络和其他所有场景的缓存策略支持,以及频繁调用请求的丢弃策略. 特性 1.基于Retrofit的二次 ...
- Android 应用程序集成FaceBook 登录及二次封装
1.首先在Facebook 开发者平台注册一个账号 https://developers.facebook.com/ 开发者后台 https://developers.facebook.com/ap ...
最新文章
- 共享数字经济之光!世界互联网大会重磅发布“30位新生代数字经济人才”
- 程序设计第三次作业附加 代码规范
- onvif规范的实现:成功实现ONVIF协议RTSP-Video-Stream与OnvifDeviceManager的视频对接
- 设置在VS2005的IDE中迅速打开xaml文件
- webpack loader使用
- 无人驾驶入门(camera篇)
- motion的移植和使用
- E - A very hard mathematic problem----(2015 summer training #3)
- Sql server 2008 Express 下载
- IOS平台车牌识别技术简介
- 解决Eclipse保存web.xml卡的问题
- 你和你的女神之间,差了一个OpenCV口红色号识别器,android开发环境的搭建步骤
- 2022-05-30 无法验证是否已安装所需的Microsoft更新KB2919355
- linux中如何安装windows
- python中\t \r \s \n \f各种转移字符含义
- NTC(负温度)热敏电阻.阻值的计算方式
- 通过 Github Actions 部署 Mkdocs 文档
- nodejs typeorm oneToManymanyToOne详细用法
- 基于matlab的汽车牌照识别研究
- Sentinel-2 (哨兵2号) 数据批量下载教程 [python]
热门文章
- 自动执行任务_中小企业如何做运维自动化?
- vs code快捷键修改为idea快捷键
- 虎牙改名字服务器升级维护中,王一博“虎牙直播”被占id,无奈改了名字,新名字却被吐槽...
- 【CCCC】L2-008 最长对称子串 (25分),直接枚举遍历
- 【NOIP2007】【Luogu1093】奖学金
- java一行输入多个数据类型_Java中的3种输入方式实现解析
- vwap算法下单_时间加权平均价格算法(TWAP)和成交量平均算法(VWAP)在量化回测的应用...
- docker host模式拿到nginx远程ip端口_FastDFS基于Docker安装,免采坑版
- 第二章节 ASP.NET 验证控件(二)
- java数组子类型_在vhdl中获取数组子类型的范围属性