MBProgress HUD 1.0.0 Source Parsing

MBProgress HUD is a tripartite library for displaying prompt windows, which is often used for user interaction, background time-consuming operations and other prompts. By displaying a prompt box, the user can be notified of the status of operation or task execution. At the same time, the animation effect can be used to reduce the anxiety of the user and enhance the user experience.

This article from the source point of view to see how MBProgress HUD is implemented, the knowledge used is relatively basic, but it is worth learning. Details are as follows:

1. Class Introduction

  • MBProgressHUD
    This is the main class of MBProgressHUD, which provides rich attributes to adjust the style of views.
  • MBRoundProgressView
    This is the class that provides the Determinate view display. There are two ways: non-circular view and circular view.
  • MBBarProgressView
    This is the view class that provides the progress bar.
  • MBBackgroundView
    This is the background view class of MBProgressHUD, which uses UIVisual EffectView to provide ground glass effect.

2. Display mode of MBProgressHUD class

  • MBProgressHUDModeIndeterminate



  • MBProgressHUDModeDeterminate



  • MBProgressHUDModeDeterminateHorizontalBar



  • MBProgressHUDModeAnnularDeterminate



  • MBProgressHUDModeCustomView

This is a custom view

  • MBProgressHUDModeText



3. Animation mode

  • MBProgress HUDAnimation Fade: Gradient Mode
  • MBProgressHUDAnimationZoom : Zoom In & Zoom Out
  • MBProgress HUD Animation ZoomOut: Small animations when disappeared
  • MBProgress HUD Animation ZoomIn: animation with larger bands when it appears

4. Background Style

  • MBProgressHUDBackgroundStyleSolidColor: Normal color
  • MBProgress HUDBackgroundStyle Blur: Ground Glass Effect

5. View content

  • @ property (strong, nonatomic, readonly) UILabel *label;: Title
  • @ property (strong, nonatomic, readonly) UILabel *detailsLabel;: Details
  • @ property (strong, nonatomic, readonly) UIButton *button: Button (shown below the title)
  • @ property (strong, nonatomic, nullable) UIView *customView;: User-defined view
  • @ property (strong, nonatomic, readonly) MBBackgroundView *backgroundView;: Whole Background View
  • @ property (strong, nonatomic, readonly) MBBackgroundView *bezelView;: Tip box background view
  • @ property (strong, nonatomic, nullable) UIColor *contentColor UI_APPEARANCE_SELECTOR;: The content color of the prompt box
  • @ property (assign, nonatomic) CGPoint offset UI_APPEARANCE_SELECTOR;: The offset of the prompt box from the center of the parent view
  • @ property (assign, nonatomic) CGFloat margin UI_APPEARANCE_SELECTOR;: Margin of the content view in the prompt box
  • @ property (assign, nonatomic) CGSize minSize UI_APPEARANCE_SELECTOR;: Minimum size of prompt box
  • @ property (assign, nonatomic) BOOL removeFromSuperViewOnHide;: Delete from parent view when hiding
  • @ Property (assign, non-atomic) NSTime Interval graceTime: How long will the prompt box be displayed after the delay, so as to avoid fast tasks and display the prompt box, which will cause visual interference to users.
  • @ Property (assign, nonatomic) NSTime Interval minShowTime;: Tip box view with minimum display time

6. Create and hide views

  • Create a process
    Views can be created either by using the + (instance type) showHUDAddedTo:(UIView*) view animated:(BOOL) animated class method or by using object method, but it is suggested that class method not only be convenient to create, but also be automatically added to the parent view and then displayed. Among them, the creation process is as follows:
- (void)commonInit {
    // Set default values for properties
    _animationType = MBProgressHUDAnimationFade;
    _mode = MBProgressHUDModeIndeterminate;
    _margin = 20.0f;
    _opacity = 1.f;
    _defaultMotionEffectsEnabled = YES;

    // Default color, depending on the current iOS version
    BOOL isLegacy = kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_7_0; 
    _contentColor = isLegacy ? [UIColor whiteColor] : [UIColor colorWithWhite:0.f alpha:0.7f]; 
    // Transparent background self.opaque = NO; 
    self.backgroundColor = [UIColor clearColor]; 
    // Make it invisible for now self.alpha = 0.0f; 
    self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.layer.allowsGroupOpacity = NO; 
    [self setupViews]; [self updateIndicators]; 
    [self registerForNotifications]; 
} 

We can find that after adding subspace, we call updateIndicators method to create different views according to view mode, and finally add a status bar notification to jump the view when the screen is horizontal and vertical. When displaying the prompt box, graceTime will be judged first. If the time is not zero, then a timer countdown will be created. After that, the task will be judged whether it is finished or not. If finished is not empty, the prompt box will be displayed.

- (void)showAnimated:(BOOL)animated {
    MBMainThreadAssert();
    [self.minShowTimer invalidate];
    self.useAnimation = animated;
    self.finished = NO;
    // If the grace time is set, postpone the HUD display
    if (self.graceTime > 0.0) {
        NSTimer *timer = [NSTimer timerWithTimeInterval:self.graceTime target:self selector:@selector(handleGraceTimer:) userInfo:nil repeats:NO];
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
        self.graceTimer = timer;
    } 
    // ... otherwise show the HUD immediately
    else {
        [self showUsingAnimation:self.useAnimation];
    }
}
- (void)handleGraceTimer:(NSTimer *)theTimer 
{ 
    // Show the HUD only if the task is still running 
    if (!self.hasFinished) { 
        [self showUsingAnimation:self.useAnimation]; 
    } 
} 
  • Hidden views are hidden by +(BOOL) hideHUDForView:(UIView*) view animated:(BOOL) animated view, which determines whether to hide prompt box immediately according to minShowTime. If minShowTime is not zero, a timer is created and added to the common mode runloop, and the prompt box is hidden later.
- (void)hideAnimated:(BOOL)animated 
{    
    MBMainThreadAssert();
    [self.graceTimer invalidate];
    self.useAnimation = animated;
    self.finished = YES;
    // If the minShow time is set, calculate how long the HUD was shown,
    // and postpone the hiding operation if necessary
    if (self.minShowTime > 0.0 && self.showStarted) {
        NSTimeInterval interv = [[NSDate date] timeIntervalSinceDate:self.showStarted];
        if (interv < self.minShowTime) {
            NSTimer *timer = [NSTimer timerWithTimeInterval:(self.minShowTime - interv) target:self selector:@selector(handleMinShowTimer:) userInfo:nil repeats:NO];
            [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
            self.minShowTimer = timer;
            return;
        } 
    }
    // ... otherwise hide the HUD immediately
    [self hideUsingAnimation:self.useAnimation];
}

7. MBRound ProgressView and MBB Car ProgressView

These two classes, respectively, create the deterate and progress bar prompt box view, the specific implementation method is in the -(void)drawRect:(CGRect)rect method through UIBezierPath or Quarts2D drawing, the design idea is conventional, please refer to the code for close reading.

8. MBProgress HUD application

For tripartite frameworks, it is better to encapsulate a layer (inheritance or classification) before using it, so as to facilitate future debugging and replacement of new frameworks. When encapsulating, use class method as far as possible and use it concisely.
* Add prompt box

+ (void)showHUDWithText:(NSString *)text inView:(UIView *)view deley:(NSTimeInterval)time
{
    if (text == nil || text.length <= 0) {
        return;
    }

    if (view == nil) {
        view = [[UIApplication sharedApplication].windows lastObject];
    }

    MBProgressHUD *HUD = [MBProgressHUD showHUDAddedTo:view animated:YES];
    HUD.mode = MBProgressHUDModeText;

    [HUD hideAnimated:YES afterDelay:1.5];
}
  • Hide the prompt box (when changing method calls, it's better to be in the main thread, asynchronous threads may have problems)
+ (void)hideHUDForView:(UIView *)view
{
    if (view == nil) view = [[UIApplication sharedApplication].windows lastObject];
    [self hideHUDForView:view animated:YES];
}

Reference material

https://github.com/jdg/MBProgressHUD

Keywords: Windows iOS github

Added by kaser on Thu, 13 Jun 2019 01:57:09 +0300