开源项目:MMPopupView

前言


弹出框组件应该是绝大多数应用都少不了的(只有极少数精心设计的APP会用不到) 当然我们的APP也不例外 之前我们APP的弹出框组件是我用pop写的 可是后来发现与系统原生动画有些冲突(pop内部用到了CATransaction 导致跟系统动画同时发生时会有问题) 所以上周花了大半天时间重写了一下MMPopupView这个组件

因为新写的组件完全是用Masonry写的 我觉得是个非常好的示例教程 结合之前我写的Masonry入门教程 应该可以更好的理解和运用Masonry/Autolayout 所以我又花了一点时间重新整理成了一个简单的开源库 有兴趣的朋友可以研究一下

运行的demo可以在这里查看

介绍


整体的组成大概就是这个样子

MMPopupWindow就是用来显示所有弹出框的容器 相对直接显示在当前UIWindow上来说 弄个独立的Window出来当容器的会更好

MMPopupView就是弹出框的基类 所有的弹出框只要继承自这个类 就具备了显示的能力 用户只要关注于弹出框本身的表现就行了

MMAlertViewMMSheetView都是我提供的基于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
23
@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
62
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是用于MMAlertViewMMSheetView的动作对象(对应按钮) 定义如下

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];

自定义


除了使用MMAlertViewMMSheetView之外 比如我们的应用中会用到输入验证码的提示框和日期的选择框 都可以用MMPopupView来轻松实现

小结


源码和Demo请点这里

更多的细节欢迎运行demo 或者查看源代码 有任何问题欢迎提出来大家一起讨论研究 :)