MBProgressHUD源碼淺析

最近項目需要添加提示控件(HUD),想著參考一下別人的源碼再封裝,然后就找了MBProgressHUD,然后記錄下。

框架使用起來很簡單:

[MBProgressHUD showHUDAddedTo:self.view animated:YES];
[MBProgressHUD hideHUDForView:self.view animated:YES];
源碼
  1. MBProgressHUD就是展示一個封裝的UIView,大小根據(jù)傳入的view鋪滿(由于背景鋪滿,所以可控制展示時不能點擊其他視圖),于是想要什么提示效果便可以自己實現(xiàn)(MBProgressHUD可以修改customViewlabel):
@interface MBProgressHUD : UIView
@implementation MBProgressHUD

+ (instancetype)showHUDAddedTo:(UIView *)view animated:(BOOL)animated {
    MBProgressHUD *hud = [[self alloc] initWithView:view];
    hud.removeFromSuperViewOnHide = YES;
    [view addSubview:hud];//添加
    [hud showAnimated:animated];
    return hud;
}

- (id)initWithView:(UIView *)view {
    NSAssert(view, @"View must not be nil.");
    return [self initWithFrame:view.bounds];
}

- (instancetype)initWithFrame:(CGRect)frame {
    if ((self = [super initWithFrame:frame])) {
        [self commonInit];
    }
    return self;
}

- (void)commonInit {
     ...
    [self setupViews];//設置子視圖
    [self updateIndicators];//設置指示器
    [self registerForNotifications];//注冊通知
}
  1. 然后進行展示:
- (void)showAnimated:(BOOL)animated {
    ...
    else {
        [self showUsingAnimation:self.useAnimation];
    }
}

- (void)showUsingAnimation:(BOOL)animated {
    ...
    if (animated) {
        [self animateIn:YES withType:self.animationType completion:NULL];
    } else {
        self.bezelView.alpha = 1.f;
        self.backgroundView.alpha = 1.f;
    }
}
  1. 隱藏時循環(huán)獲?。?/li>
+ (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated {
    MBProgressHUD *hud = [self HUDForView:view];
    if (hud != nil) {
        hud.removeFromSuperViewOnHide = YES;
        [hud hideAnimated:animated];
        return YES;
    }
    return NO;
}

+ (MBProgressHUD *)HUDForView:(UIView *)view {
    NSEnumerator *subviewsEnum = [view.subviews reverseObjectEnumerator];
    for (UIView *subview in subviewsEnum) {
        if ([subview isKindOfClass:self]) {
            MBProgressHUD *hud = (MBProgressHUD *)subview;
            if (hud.hasFinished == NO) {
                return hud;
            }
        }
    }
    return nil;
}

- (void)hideAnimated:(BOOL)animated {
    ...
    [self hideUsingAnimation:self.useAnimation];
}

- (void)hideUsingAnimation:(BOOL)animated {
    ...
    if (animated && self.showStarted) {
        self.showStarted = nil;
        [self animateIn:NO withType:self.animationType completion:^(BOOL finished) {
            [self done];
        }];
    } else {
        self.showStarted = nil;
        self.bezelView.alpha = 0.f;
        self.backgroundView.alpha = 1.f;
        [self done];
    }
}

- (void)animateIn:(BOOL)animatingIn withType:(MBProgressHUDAnimation)type completion:(void(^)(BOOL finished))completion {
    ...
    [UIView animateWithDuration:0.3 delay:0. usingSpringWithDamping:1.f initialSpringVelocity:0.f options:UIViewAnimationOptionBeginFromCurrentState animations:animations completion:completion];
}
  1. 最終調(diào)用done進行移除并進行相應回調(diào):
- (void)done {
    [self setNSProgressDisplayLinkEnabled:NO];

    if (self.hasFinished) {
        self.alpha = 0.0f;
        if (self.removeFromSuperViewOnHide) {
            [self removeFromSuperview];//移除
        }
    }
    //進行回調(diào)
    MBProgressHUDCompletionBlock completionBlock = self.completionBlock;
    if (completionBlock) {
        completionBlock();
    }
    id<MBProgressHUDDelegate> delegate = self.delegate;
    if ([delegate respondsToSelector:@selector(hudWasHidden:)]) {
        [delegate performSelector:@selector(hudWasHidden:) withObject:self];
    }
}
流程
  • SVProgressHUD的對比

SVProgressHUD類對外提供的都是類方法,其內(nèi)部實現(xiàn)為一個單例對象。
SVProgressHUD主要包含三部分:loading視圖、提示文本框和背景框,沒有詳情文本框。
SVProgressHUD默認提供了正確、錯誤和信息三種狀態(tài)視圖。
SVProgressHUD為我們提供了更多的交互操作,包括點擊事件、顯示事件及隱藏事件。不過這些都是通過通知的形式向外發(fā)送,所以我們需要自己去監(jiān)聽這些事件。
SVProgressHUD中一些loading動畫是以Layer動畫的形式來實現(xiàn)的。

  • 自己封裝

如果自己封裝一個簡單的HUD,就是添加一個自定義UIView控件到頁面上方,自己可以在實現(xiàn)對應效果,然后展示或隱藏。

  1. 我直接添加到UIWindow上全局使用,然后用hiden控制展示和隱藏.

  2. 可能計算自適應label會有點麻煩,因為沒有用約束.

  3. 然后自己用UIActivityIndicatorView作為加載提示器,發(fā)現(xiàn)太小,使用transform變大后通過Debug View Hierarchy發(fā)現(xiàn)菊花圖案有右/下邊距,沒法居中,于是自己使用CAShapeLayer、UIBezierPathCABasicAnimation寫了簡陋的提示效果:

  1. 注意處理同時顯示隱藏操作的沖突問題。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 源碼來源:gitHub源碼 轉(zhuǎn)載于: CocoaChina 來源:南峰子的技術(shù)博客 版本:0.9.1 MBPr...
    李小六_閱讀 6,564評論 2 5
  • 16宿命:用概率思維提高你的勝算 以前的我是風險厭惡者,不喜歡去冒險,但是人生放棄了冒險,也就放棄了無數(shù)的可能。 ...
    yichen大刀閱讀 7,871評論 0 4
  • 公元:2019年11月28日19時42分農(nóng)歷:二零一九年 十一月 初三日 戌時干支:己亥乙亥己巳甲戌當月節(jié)氣:立冬...
    石放閱讀 7,457評論 0 2

友情鏈接更多精彩內(nèi)容