MBProgressHUD1.0.0源碼解析

来源:http://www.cnblogs.com/fishbay/archive/2017/07/18/7198749.html
-Advertisement-
Play Games

`MBProgressHUD`是一個顯示提示視窗的三方庫,常用於用戶交互、後臺耗時操作等的提示。通過顯示一個提示框,通知用戶操作或任務的執行狀態;同時,利用動畫效果,降低用戶等待的焦慮心理,增強用戶體驗。 本篇文章從源碼角度來看一下 是如何實現的,所用的知識都是比較基礎的,不過還是值得我們學習一下。 ...


MBProgressHUD是一個顯示提示視窗的三方庫,常用於用戶交互、後臺耗時操作等的提示。通過顯示一個提示框,通知用戶操作或任務的執行狀態;同時,利用動畫效果,降低用戶等待的焦慮心理,增強用戶體驗。

本篇文章從源碼角度來看一下MBProgressHUD是如何實現的,所用的知識都是比較基礎的,不過還是值得我們學習一下。詳解如下:

1. 類介紹

  • MBProgressHUD
    這是MBProgressHUD的主要類,提供豐富的屬性來調整視圖的樣式。
  • MBRoundProgressView
    這是提供Determinate視圖顯示的類,有非圓環和圓環視圖兩種方式。
  • MBBarProgressView
    這是提供進度條的視圖類。
  • MBBackgroundView
    這是MBProgressHUD的背景視圖類,利用UIVisualEffectView提供毛玻璃效果

2. MBProgressHUD類的顯示模式

  • MBProgressHUDModeIndeterminate
![Indeterminate](http://upload-images.jianshu.io/upload_images/1843940-7d2ced265a958ace.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  • MBProgressHUDModeDeterminate
![Determinate](http://upload-images.jianshu.io/upload_images/1843940-0729bfea6d1ffb75.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  • MBProgressHUDModeDeterminateHorizontalBar
![DeterminateHorizontalBar](http://upload-images.jianshu.io/upload_images/1843940-24816377417a2ade.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  • MBProgressHUDModeAnnularDeterminate
![AnnularDeterminate](http://upload-images.jianshu.io/upload_images/1843940-37b8afa115eb5fe8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  • MBProgressHUDModeCustomView

這是自定義視圖

  • MBProgressHUDModeText
![Text](http://upload-images.jianshu.io/upload_images/1843940-ca92d0d489e9c287.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

3.動畫模式

  • MBProgressHUDAnimationFade : 漸變模式
  • MBProgressHUDAnimationZoom : Zoom In & Zoom Out
  • MBProgressHUDAnimationZoomOut : 消失時帶變小動畫
  • MBProgressHUDAnimationZoomIn : 出現時帶變大動畫

4. 背景樣式

  • MBProgressHUDBackgroundStyleSolidColor : 正常顏色
  • MBProgressHUDBackgroundStyleBlur : 毛玻璃效果

5. 視圖內容

  • @property (strong, nonatomic, readonly) UILabel *label; : 標題
  • @property (strong, nonatomic, readonly) UILabel *detailsLabel; :詳情
  • @property (strong, nonatomic, readonly) UIButton *button : 按鈕(顯示在標題下方)
  • @property (strong, nonatomic, nullable) UIView *customView; :用戶自定義視圖
  • @property (strong, nonatomic, readonly) MBBackgroundView *backgroundView; : 整個背景視圖
  • @property (strong, nonatomic, readonly) MBBackgroundView *bezelView; :提示框背景視圖
  • @property (strong, nonatomic, nullable) UIColor *contentColor UI_APPEARANCE_SELECTOR; : 提示框的內容顏色
  • @property (assign, nonatomic) CGPoint offset UI_APPEARANCE_SELECTOR; :提示框相對父視圖中心點的偏移量
  • @property (assign, nonatomic) CGFloat margin UI_APPEARANCE_SELECTOR; :提示框內的內容視圖的邊距
  • @property (assign, nonatomic) CGSize minSize UI_APPEARANCE_SELECTOR; :提示框最小尺寸
  • @property (assign, nonatomic) BOOL removeFromSuperViewOnHide; :隱藏時從父視圖中刪除
  • @property (assign, nonatomic) NSTimeInterval graceTime; :延遲多久後顯示提示框,避免快速執行的任務也顯示提示框,給用戶造成視覺干擾。
  • @property (assign, nonatomic) NSTimeInterval minShowTime; :提示框視圖最少展示的時間

6. 創建和隱藏視圖

  • 創建流程
    通過 + (instancetype)showHUDAddedTo:(UIView *)view animated:(BOOL)animated 類方法創建視圖,也可以通過對象方法創建,不過建議用類方法,不僅創建方便,而且會自動的添加到父視圖,然後進行顯示。其中,創建過程如下:
- (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]; 
} 

我們可以發現,通過添加子空間後,根據視圖模式調用updateIndicators方法來創建不同的視圖,最後添加了一個狀態欄的通知,用來在橫豎屏時跳轉視圖。其中,在顯示提示框時,會首先判斷graceTime,如過不為0,那麼就創建一個定時器倒計時,時間到之後再判斷任務是否結束,如果finished 不為空,就開始顯示提示框。

- (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]; 
    } 
} 
  • 隱藏視圖 通過 + (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated 隱藏視圖,其中會根據minShowTime來判斷是否立即隱藏提示框。如果,minShowTime 不為0,那麼會創建一個定時器,並把定時器加入到common模式的runloop里,等時間到後再把提示框隱藏。
- (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. MBRoundProgressView 和 MBBarProgressView

這兩個類,分別創建了 Determinate 和 進度條 的提示框視圖,具體實現方法是在 - (void)drawRect:(CGRect)rect 方法里通過 UIBezierPath 或者 Quarts2D 畫出,設計思想算是常規,請參考代碼細讀。

8. MBProgressHUD應用

對於三方框架,使用之前,最好先封裝一層(繼承或分類),方便以後的調試和新框架替換。封裝時,儘量用類方法,使用時比較簡潔。

  • 添加提示框
+ (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];
}
  • 隱藏提示框 (改方法調用時,最好在主線程,非同步線程可能會出現問題)
+ (void)hideHUDForView:(UIView *)view
{
    if (view == nil) view = [[UIApplication sharedApplication].windows lastObject];
    [self hideHUDForView:view animated:YES];
}

參考資料

https://github.com/jdg/MBProgressHUD


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文主要分享一下博主在學習wxpy 的過程中開發的一個小程式。博主在最近有一個監控報警的需求需要完成,然後剛好在學習wxpy 這個東西,因此很巧妙的將工作和學習聯繫在一起。   博文中主要使用到的技術設計到Python,Redis,以及Java。涉及到的技術看似很多,但是主要的語言是基於Pytho... ...
  • Spring Boot 熱部署 實際開發中,修改某個頁面數據或邏輯功能都需要重啟應用。這無形中降低了開發效率,所以使用熱部署是十分必要的。 什麼是熱部署? 應用啟動後會把編譯好的Class文件載入的虛擬機中,正常情況下在項目修改了源文件是需要全部重新編譯並重新載入(需要重啟應用)。而熱部署就是監聽C ...
  • 1 概述 1 概述 軟體架構是一門學問,並且是一門很深邃的學問,從本篇文章開始,我們就來聊聊架構,所用到的主流語言為.NET、Java和php。本篇文章作為架構的開篇文章,主要從廣度上敘述軟體架構的發展與演變,從軟體架構系列第二篇文章開始,將結合具體的產品或項目實例,來與大家分享架構。 本篇文章先簡 ...
  • 使用docker也有段時間了,寫了不少文章與總結,下麵把它整理個目錄出來,方便大家去學習與檢索! docker~學習筆記索引 docker~linux下的部署和基本命令(2017-04-07 22:47) docker~docker-machine的介紹(2017-04-12 12:02) dock ...
  • HP-Socket 是一套通用的高性能 TCP/UDP/HTTP 通信框架,包含服務端組件、客戶端組件和 Agent 組件,廣泛適用於各種不同應用場景的 TCP/UDP/HTTP 通信系統,提供 C/C++、C#、Delphi、E(易語言)、Java、Python 等編程語言介面。HP-Socket... ...
  • 代碼: #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any a ...
  • 目前將項目中的leancloud的即時通訊改為環信的即時通訊。當引入easeui的時候 出現方法數超過上限的問題。 搜索一下問題,解決方法很簡單。 這裡簡單記錄一下,順序記錄一下此解決方案導致的另一個問題。 一、解決方法數超過64k的問題 問題描述: 解決方案: 1、app目錄下 build.gra ...
  • 思路 思路很簡單,對模型數據操作或則控制界面顯示 先看下json部分數據 這種數據對應的一般都是個tableView, 然後根據章節分開,最終界面如下: 分析 這裡採用UITableViewStylePlain樣式,chapterDtoList對應章,subChapterList對應節。章的話我們使 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...