MMPopupView 源碼分析

az6659208 8年前發布 | 7K 次閱讀 源碼分析 iOS開發 移動開發

MMPopupView 是什么

MMPopupView 是一個基于UIWindow的一個簡潔、高效的彈出框組件,其中包括 :MMAlertView & MMSheetView 這兩種內置的展示效果,另外開發者也可以自定義彈出視圖以及相關事務;

typedef NS_ENUM(NSUInteger, MMPopupType) {
    MMPopupTypeAlert,
    MMPopupTypeSheet,
    MMPopupTypeCustom,
};

來源

 

MMPopupView 適用場景

MMPopupView 可適用于照片選擇、時間選擇、性別選擇彈出框以及提示、警告、以及自定義彈出框的搭建;

MMPopupView 工作邏輯

  1. 層次結構

  2. MMPopupView 是基于 UIWindow 展現彈出框的基類的,但與相對直接基于當前 UIWindow 來說,它用 MMPopupWindow 這個UIWindow 單例來顯示或隱藏所有彈出框的容器,并處理相關的手勢事件;
  3. MMPopupView 通過 維護和管理 MMPopupItem 結構數組 來管理包括 高亮、顏色、是否可用、標題、block等單元屬性;
  4. MMPopupView 使用自己的 Category 來完成最后的 視圖填充、視圖動畫、視圖約束、背景顏色、UIWindow 隱藏和展示等;
@property (nonatomic, strong, readonly ) UIView            *mm_dimBackgroundView;
@property (nonatomic, assign, readonly ) BOOL              mm_dimBackgroundAnimating;
@property (nonatomic, assign           ) NSTimeInterval    mm_dimAnimationDuration;

@property (nonatomic, strong, readonly ) UIView *mm_dimBackgroundBlurView; @property (nonatomic, assign ) BOOL mm_dimBackgroundBlurEnabled; @property (nonatomic, assign ) UIBlurEffectStyle mm_dimBackgroundBlurEffectStyle;

  • (void) mm_showDimBackground;
  • (void) mm_hideDimBackground;

  • (void) mm_distributeSpacingHorizontallyWith:(NSArray*)view;

  • (void) mm_distributeSpacingVerticallyWith:(NSArray*)view;</code></pre>

    MMPopupView 實現細節

    • MMPopupWindow的定義如下:

    @interface MMPopupWindow : UIWindow

@property (nonatomic, assign) BOOL touchWildToHide; // default is NO. When YES, popup views will be hidden when user touch the translucent background. @property (nonatomic, readonly) UIView* attachView;

  • (MMPopupWindow *)sharedWindow;

/**

  • cache the window to prevent the lag of the first showing. */
    • (void) cacheWindow;

@end</code></pre>

很簡單 只有一個屬性 touchWildToHide 用來控制是否可以點擊非彈出框的地方來使彈出框消失 還有一個 cacheWindow 的方法來預加載 MMPopupWindow 防止第一次使用的時候頓卡;

  • MMPopupWindow 定義如下:

typedef NS_ENUM(NSUInteger, MMPopupType) {
    MMPopupTypeAlert,
    MMPopupTypeSheet,
    MMPopupTypeCustom,
};

@class MMPopupView;

typedef void(^MMPopupBlock)(MMPopupView ); typedef void(^MMPopupCompletionBlock)(MMPopupView , BOOL);

@interface MMPopupView : UIView

@property (nonatomic, assign, readonly) BOOL visible; // default is NO.

@property (nonatomic, strong ) UIView *attachedView; // default is MMPopupWindow. You can attach MMPopupView to any UIView.

@property (nonatomic, assign ) MMPopupType type; // default is MMPopupTypeAlert. @property (nonatomic, assign ) NSTimeInterval animationDuration; // default is 0.3 sec. @property (nonatomic, assign ) BOOL withKeyboard; // default is NO. When YES, alert view with be shown with a center offset (only effect with MMPopupTypeAlert).

@property (nonatomic, copy ) MMPopupCompletionBlock showCompletionBlock; // show completion block. @property (nonatomic, copy ) MMPopupCompletionBlock hideCompletionBlock; // hide completion block

@property (nonatomic, copy ) MMPopupBlock showAnimation; // custom show animation block. @property (nonatomic, copy ) MMPopupBlock hideAnimation; // custom hide animation block.

/**

  • override this method to show the keyboard if with a keyboard */
    • (void) showKeyboard;

/**

  • override this method to hide the keyboard if with a keyboard */
    • (void) hideKeyboard;

/**

  • show the popup view */
    • (void) show;

/**

  • show the popup view with completiom block *
  • @param block show completion block */
    • (void) showWithBlock:(MMPopupCompletionBlock)block;

/**

  • hide the popup view */
    • (void) hide;

/**

  • hide the popup view with completiom block *
  • @param block hide completion block */
    • (void) hideWithBlock:(MMPopupCompletionBlock)block;

/**

  • hide all popupview with current class, eg. [MMAlertview hideAll]; */
    • (void) hideAll;

@end</code></pre>

包括,PopupView 類型、時間、可見、show 與 hide 的block 事件等;

其中 - hideWithBlock 和 hideWithBlock 展現和隱藏 外部方法,并通過

其中 PopupView 內部也包含 alert、sheet、custom 的展現于隱藏的動畫事務;

- (MMPopupBlock)alertShowAnimation

  • (MMPopupBlock)alertHideAnimation

  • (MMPopupBlock)sheetShowAnimation

  • (MMPopupBlock)sheetHideAnimation

  • (MMPopupBlock)customShowAnimation

  • (MMPopupBlock)customHideAnimation</code></pre>

    以 alertShowAnimation 為例:

    - (MMPopupBlock)alertShowAnimation
    {
      MMWeakify(self);
      MMPopupBlock block = ^(MMPopupView *popupView){

      MMStrongify(self);
    
      if ( !self.superview )
      {
          [self.attachedView.mm_dimBackgroundView addSubview:self];
          [self mas_updateConstraints:^(MASConstraintMaker *make) {
              make.center.equalTo(self.attachedView).centerOffset(CGPointMake(0, self.withKeyboard?-216/2:0));
          }];
          [self layoutIfNeeded];
      }
    
      self.layer.transform = CATransform3DMakeScale(1.2f, 1.2f, 1.0f);
      self.alpha = 0.0f;
    
      [UIView animateWithDuration:self.animationDuration
                            delay:0.0 options:UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionBeginFromCurrentState
                       animations:^{
    
                           self.layer.transform = CATransform3DIdentity;
                           self.alpha = 1.0f;
    
                       } completion:^(BOOL finished) {
    
                           if ( self.showCompletionBlock )
                           {
                               self.showCompletionBlock(self, finished);
                           }
                       }];
    

    };

    return block; }</code></pre>

    添加到 將popupView 添加到 _attachedView 更新約束、渲染 并 執行相關動畫;

    • MMPopupView 核心拓展類定義如下:

    @interface UIView (MMPopup)

@property (nonatomic, strong, readonly ) UIView *mm_dimBackgroundView; @property (nonatomic, assign, readonly ) BOOL mm_dimBackgroundAnimating; @property (nonatomic, assign ) NSTimeInterval mm_dimAnimationDuration;

@property (nonatomic, strong, readonly ) UIView *mm_dimBackgroundBlurView; @property (nonatomic, assign ) BOOL mm_dimBackgroundBlurEnabled; @property (nonatomic, assign ) UIBlurEffectStyle mm_dimBackgroundBlurEffectStyle;

  • (void) mm_showDimBackground;
  • (void) mm_hideDimBackground;

  • (void) mm_distributeSpacingHorizontallyWith:(NSArray*)view;

  • (void) mm_distributeSpacingVerticallyWith:(NSArray*)view;

@end</code></pre>

包括 MMPopWindow 已經 MMPopupView 的 subviews 新增、相關約束以及hide & show,這是整個類庫執行的最終落腳點

MMPopupView 幾點啟示

MMPopupView 源碼本身并不復雜,但仍然有許多可以借鑒學習的地方:

@interface UIViewController(MAC)

pragma mark 設置 展示AlertView or SheetView

/**

  • 展示Alert提示信息 / -(void)showAlertMessage:(NSString)message;

/**

  • 展示Alert提示信息 / -(void)showAlertMessage:(NSString)message titile:(NSString *)title; /**
  • 展示Alert提示信息 *
  • @param message 提示內容
  • @param title 提示標題
    • @param clickArr 按鈕信息數組
  • @param clickIndex 點擊的下標 / -(void)showAlertMessage:(NSString )message title:(NSString )title clickArr:(NSArray )arr click:(MMPopupItemHandler) clickIndex; /**
  • 展示SheetView提示信息 *
  • @param title 提示標題
  • @param clickArr 按鈕信息數組
  • @param clickIndex 點擊的下標 / -(void)showSheetTitle:(NSString )title clickArr:(NSArray *)arr click:(MMPopupItemHandler) clickIndex;</code></pre>

    UIViewController+MAC.m

    @implementation UIViewController(MAC)

-(void)showAlertMessage:(NSString*)message { [self showAlertMessage:message titile:@"提示"];

} -(void)showAlertMessage:(NSString)message titile:(NSString )title{ MMPopupItemHandler block = ^(NSInteger index){ NSLog(@"clickd %@ button",@(index)); }; NSArray *items = @[MMItemMake(@"確定", MMItemTypeHighlight, block)];

MMAlertView *alertView = [[MMAlertView alloc] initWithTitle:title
                                                     detail:message
                                                      items:items];

[alertView show];

} -(void)showAlertMessage:(NSString )message title:(NSString )title clickArr:(NSArray )arr click:(MMPopupItemHandler) clickIndex{ if (!arr||arr.count<=0) { return; } __block NSMutableArray items=[NSMutableArray array]; [arr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL _Nonnull stop) { [items addObject:MMItemMake(obj, MMItemTypeHighlight, clickIndex)]; }]; MMAlertView alertView = [[MMAlertView alloc] initWithTitle:title detail:message items:items]; [alertView show]; } -(void)showSheetTitle:(NSString )title clickArr:(NSArray )arr click:(MMPopupItemHandler)clickIndex{ if (!arr||arr.count<=0) { return; }

__block NSMutableArray *items=[NSMutableArray array];
[arr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    [items addObject:MMItemMake(obj, MMItemTypeHighlight, clickIndex)];
}];
[[[MMSheetView alloc] initWithTitle:title
                              items:items] show];

};</code></pre>

 

來自:http://www.jianshu.com/p/c5ebd455ee82

 

 本文由用戶 az6659208 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!