前言
彈出框元件應該是絕大多數應用都少不了的(只有極少數精心設計的APP會用不到) 當然我們的APP也不例外 之前我們APP的彈出框元件是我用pop寫的 可是後來發現與系統原生動畫有些衝突(pop內部用到了CATransaction 導致跟系統動畫同時發生時會有問題) 所以上週花了大半天時間重寫了一下MMPopupView這個元件
因為新寫的元件完全是用Masonry寫的 我覺得是個非常好的示例教程 結合之前我寫的Masonry入門教程 應該可以更好的理解和運用Masonry/Autolayout 所以我又花了一點時間重新整理成了一個簡單的開源庫 有興趣的朋友可以研究一下
執行的demo可以在這裡檢視
介紹
整體的組成大概就是這個樣子
MMPopupWindow就是用來顯示所有彈出框的容器 相對直接顯示在當前UIWindow上來說 弄個獨立的Window出來當容器的會更好
MMPopupView就是彈出框的基類 所有的彈出框只要繼承自這個類 就具備了顯示的能力 使用者只要關注於彈出框本身的表現就行了
MMAlertView和MMSheetView都是我提供的基於MMPopupView的簡單元件 可以直接拿來用 而且都是高度可定製的(這個稍後會介紹)
MMPopupWindow
MMPopupWindow的定義如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
@interface MMPopupWindow : UIWindow @property (nonatomic, assign) BOOL touchWildToHide; // default is NO. When YES, popup views will be hidden when user touch the translucent background. + (MMPopupWindow *)sharedWindow; /** * cache the window to prevent the lag of the first showing. */ - (void) cacheWindow; /** * show the translucent background */ - (void) showDimBackground; /** * hide the translucent background */ - (void) hideDimBackground; @end |
很簡單 只有一個屬性touchWildToHide
用來控制是否可以點選非彈出框的地方來使彈出框消失 還有一個cacheWindow
的方法來預載入MMPopupWindow 防止第一次使用的時候頓卡
另外還有兩個用於顯示和隱藏背景色的方法 這個在自定義動畫的時候會用到
1 2 |
- (void) showDimBackground; - (void) hideDimBackground; |
MMPopupView
MMPopupView的定義如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
typedef NS_ENUM(NSUInteger, MMPopupType) { MMPopupTypeAlert, MMPopupTypeSheet, MMPopupTypeCustom, }; @class MMPopupView; typedef void(^MMPopupBlock)(MMPopupView *); @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 ) MMPopupBlock showCompletionBlock; // show completion block. @property (nonatomic, copy ) MMPopupBlock 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:(MMPopupBlock)block; /** * hide the popup view */ - (void) hide; /** * hide the popup view with completiom block * * @param block hide completion block */ - (void) hideWithBlock:(MMPopupBlock)block; @end |
使用起來很簡單 定義好自己的view 然後呼叫下面的方法就好了
1 2 |
- (void) show; - (void) hide; |
你也可以指定顯示在某個UIView之上
1 |
@property (nonatomic, strong ) UIView *attachedView; |
1 2 |
- (void) show; - (void) hide; |
預設提供了三種型別 對應三種動畫效果
1 2 3 4 5 |
typedef NS_ENUM(NSUInteger, MMPopupType) { MMPopupTypeAlert, //中間隱出 MMPopupTypeSheet, //向上滑出 MMPopupTypeCustom, //向下掉落 }; |
當然你也可以自己定義想要的動畫效果 只要過載下面兩個block就行了
1 2 |
@property (nonatomic, copy) MMPopupBlock showAnimation; @property (nonatomic, copy) MMPopupBlock hideAnimation; |
同時提供了動畫的回撥 可以直接指定block或者直接呼叫方法
1 2 3 4 5 |
@property (nonatomic, copy ) MMPopupBlock showCompletionBlock; @property (nonatomic, copy ) MMPopupBlock hideCompletionBlock; - (void) showWithBlock:(MMPopupBlock)block; - (void) hideWithBlock:(MMPopupBlock)block; |
MMAlertView
MMAlertView就是UIAlertView的替代品 介面如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
typedef void(^MMPopupInputHandler)(NSString *text); @interface MMAlertView : MMPopupView @property (nonatomic, assign) NSUInteger maxInputLength; // default is 0. Means no length limit. - (instancetype) initWithInputTitle:(NSString*)title detail:(NSString*)detail placeholder:(NSString*)inputPlaceholder handler:(MMPopupInputHandler)inputHandler; - (instancetype) initWithConfirmTitle:(NSString*)title detail:(NSString*)detail; - (instancetype) initWithTitle:(NSString*)title detail:(NSString*)detail items:(NSArray*)items; @end |
分別對應下面三種形式
同時提供一個全域性的配置類 可以充分的自定義
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
@interface MMAlertViewConfig : NSObject + (MMAlertViewConfig*) globalConfig; @property (nonatomic, assign) CGFloat width; // Default is 275. @property (nonatomic, assign) CGFloat buttonHeight; // Default is 50. @property (nonatomic, assign) CGFloat innerMargin; // Default is 25. @property (nonatomic, assign) CGFloat cornerRadius; // Default is 5. @property (nonatomic, assign) CGFloat titleFontSize; // Default is 18. @property (nonatomic, assign) CGFloat detailFontSize; // Default is 14. @property (nonatomic, assign) CGFloat buttonFontSize; // Default is 17. @property (nonatomic, strong) UIColor *backgroundColor; // Default is #FFFFFF. @property (nonatomic, strong) UIColor *titleColor; // Default is #333333. @property (nonatomic, strong) UIColor *detailColor; // Default is #333333. @property (nonatomic, strong) UIColor *splitColor; // Default is #CCCCCC. @property (nonatomic, strong) UIColor *itemNormalColor; // Default is #333333. effect with MMItemTypeNormal @property (nonatomic, strong) UIColor *itemHighlightColor; // Default is #E76153. effect with MMItemTypeHighlight @property (nonatomic, strong) UIColor *itemPressedColor; // Default is #EFEDE7. @property (nonatomic, strong) NSString *defaultTextOK; // Default is "好". @property (nonatomic, strong) NSString *defaultTextCancel; // Default is "取消". @property (nonatomic, strong) NSString *defaultTextConfirm; // Default is "確定". @end |
MMSheetView
MMSheetView就是UISheetView的替代品 介面如下
1 2 3 4 5 6 |
@interface MMSheetView : MMPopupView - (instancetype) initWithTitle:(NSString*)title items:(NSArray*)items; @end |
同時提供一個全域性的配置類 可以充分的自定義
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
@interface MMSheetViewConfig : NSObject + (MMSheetViewConfig*) globalConfig; @property (nonatomic, assign) CGFloat buttonHeight; // Default is 50. @property (nonatomic, assign) CGFloat innerMargin; // Default is 19. @property (nonatomic, assign) CGFloat titleFontSize; // Default is 14. @property (nonatomic, assign) CGFloat buttonFontSize; // Default is 17. @property (nonatomic, strong) UIColor *backgroundColor; // Default is #FFFFFF. @property (nonatomic, strong) UIColor *titleColor; // Default is #666666. @property (nonatomic, strong) UIColor *splitColor; // Default is #CCCCCC. @property (nonatomic, strong) UIColor *itemNormalColor; // Default is #333333. effect with MMItemTypeNormal @property (nonatomic, strong) UIColor *itemDisableColor; // Default is #CCCCCC. effect with MMItemTypeDisabled @property (nonatomic, strong) UIColor *itemHighlightColor; // Default is #E76153. effect with MMItemTypeHighlight @property (nonatomic, strong) UIColor *itemPressedColor; // Default is #EFEDE7. @property (nonatomic, strong) NSString *defaultTextCancel; // Default is "取消" @end |
MMPopupItem
MMPopupItem是用於MMAlertView和MMSheetView的動作物件(對應按鈕) 定義如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
typedef void(^MMPopupItemHandler)(NSInteger index); @interface MMPopupItem : NSObject @property (nonatomic, assign) BOOL highlight; @property (nonatomic, assign) BOOL disabled; @property (nonatomic, strong) NSString *title; @property (nonatomic, strong) UIColor *color; @property (nonatomic, copy) MMPopupItemHandler handler; @end typedef NS_ENUM(NSUInteger, MMItemType) { MMItemTypeNormal, MMItemTypeHighlight, MMItemTypeDisabled }; NS_INLINE MMPopupItem* MMItemMake(NSString* title, MMItemType type, MMPopupItemHandler handler) { MMPopupItem *item = [MMPopupItem new]; item.title = title; item.handler = handler; switch (type) { case MMItemTypeNormal: { break; } case MMItemTypeHighlight: { item.highlight = YES; break; } case MMItemTypeDisabled: { item.disabled = YES; break; } default: break; } return item; } |
使用方式如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
//MMAlertView NSArray *items = @[MMItemMake(@"Done", MMItemTypeNormal, block), MMItemMake(@"Save", MMItemTypeHighlight, block), MMItemMake(@"Cancel", MMItemTypeNormal, block)]; [[[MMAlertView alloc] initWithTitle:@"AlertView" detail:@"each button take one row if there are more than 2 items" items:items] showWithBlock:completeBlock]; //MMSheetView NSArray *items = @[MMItemMake(@"Normal", MMItemTypeNormal, block), MMItemMake(@"Highlight", MMItemTypeHighlight, block), MMItemMake(@"Disabled", MMItemTypeDisabled, block)]; [[[MMSheetView alloc] initWithTitle:@"SheetView" items:items] showWithBlock:completeBlock]; |
自定義
除了使用MMAlertView和MMSheetView之外 比如我們的應用中會用到輸入驗證碼的提示框和日期的選擇框 都可以用MMPopupView來輕鬆實現
小結
原始碼和Demo請點這裡
更多的細節歡迎執行demo 或者檢視原始碼 有任何問題歡迎提出來大家一起討論研究 :)