自定义UIActionSheet实现分享功能,一行代码搞定!

1、先上图,有图好说话

Simulator-Screen-Shot-2016年3月13日-下午5.35.17

2、设置思路

2.1、我希望这是一个View,并非控制器,节省开支;
2.2、 这个View包含一个背景,一个面板,若干个按钮或标签;
2.3、我希望实现的功能是视图展示+事件响应;
2.4、希望无偶合性,并且一行代码搞定(能一行代码搞定的必定包含block);
2.5、这若干个按钮最好是外面传进来,要不我怎么知道需要什么样的按钮?传一组图片?那文字呢?再传一组文字?如何对应?
2.6、我希望开始调用的时候只要传按钮给你,结束后告诉我用户点了哪个按钮,其他的我都不想管(高度无偶封装),呵呵!
2.7、调用时还最好是类方法,我不喜欢alloc;
2.8、例如:+ (instancetype)sheetWithItems:(NSArray<__kindof UIButton *> *)items actionWithBlock:(SAActionSheetBlock)block

3、基本调用

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
63
64
65
66
//
//? ViewController.m
//? Test
//
//? Created by 余西安 on 16/3/11.
//? Copyright ? 2016年 Sian. All rights reserved.
//
?
#import "ViewController.h"
#import "SAActionSheet.h"
?
@interface ViewController ()
?
@end
?
@implementation ViewController
?
- (void)viewDidLoad
{
????[super viewDidLoad];
}
/// 弹出分享面板
- (IBAction)action:(UIButton *)sender
{
????[SAActionSheet sheetWithItems:[self shareItems] actionWithBlock:^(UIButton *item, NSInteger index) {
????????switch (index) {
????????????case 1: [self show:@"微信好友"]; break;
????????????case 2: [self show:@"朋友圈"]; break;
????????????case 3: [self show:@"微信收藏"]; break;
????????????case 4: [self show:@"QQ好友"]; break;
????????????case 5: [self show:@"QQ空间"]; break;
????????????default: break;
????????}
????}];
}
/// 创建按钮数组
- (NSArray *)shareItems
{
????UIImage *image1 = [UIImage imageNamed:@"Action_Share.png"];
????UIImage *image2 = [UIImage imageNamed:@"Action_Moments.png"];
????UIImage *image3 = [UIImage imageNamed:@"Action_MyFavAdd.png"];
????UIImage *image4 = [UIImage imageNamed:@"Action_QQ.png"];
????UIImage *image5 = [UIImage imageNamed:@"Action_qzone.png"];
????UIButton *button1 = [UIButton buttonWithType:UIButtonTypeSystem];
????UIButton *button2 = [UIButton buttonWithType:UIButtonTypeSystem];
????UIButton *button3 = [UIButton buttonWithType:UIButtonTypeSystem];
????UIButton *button4 = [UIButton buttonWithType:UIButtonTypeSystem];
????UIButton *button5 = [UIButton buttonWithType:UIButtonTypeSystem];
????[button1 setBackgroundImage:image1 forState:UIControlStateNormal];
????[button2 setBackgroundImage:image2 forState:UIControlStateNormal];
????[button3 setBackgroundImage:image3 forState:UIControlStateNormal];
????[button4 setBackgroundImage:image4 forState:UIControlStateNormal];
????[button5 setBackgroundImage:image5 forState:UIControlStateNormal];
????[button1 setTitle:@"微信好友" forState:UIControlStateNormal];
????[button2 setTitle:@"朋友圈" forState:UIControlStateNormal];
????[button3 setTitle:@"微信收藏" forState:UIControlStateNormal];
????[button4 setTitle:@"QQ好友" forState:UIControlStateNormal];
????[button5 setTitle:@"QQ空间" forState:UIControlStateNormal];
????return @[button1, button2, button3, button4, button5];
}
// 附属方法,显示结果
- (void)show:(NSString *)string
{
????[[[UIAlertView alloc] initWithTitle:nil message:string delegate:nil cancelButtonTitle:@"知道了" otherButtonTitles:nil, nil] show];
}
@end

4、代码实现

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//
//? SAActionSheet.m
//? fisher
//
//? Created by 余西安 on 16/3/10.
//? Copyright ? 2016年 Sian. All rights reserved.
//
#define kSAActionSheetItemColumns??? 3????? // 每行按钮数(纵列数)
#define kSAActionSheetItemWidth????? 60???? // 单个按钮长宽
#define kSAActionSheetItemSpace????? 25???? // 按钮上下之间间隔
#define kSAActionSheetLabelHeight??? 25???? // 按钮标签文字高度
#define kSAActionSheetCancelHeight?? 50???? // 取消按钮高度
#import "SAActionSheet.h"
@interface SAActionSheet ()
?
@property (nonatomic, strong) UIView??? *baseView;????? // 按钮基础板
@property (nonatomic, strong) NSArray?? *items;???????? // 按钮数组
@property (nonatomic, strong) NSArray?? *labels;??????? // 按钮标签
@property (nonatomic, strong) UIButton? *cancel;??????? // 取消按钮
@property (nonatomic, copy) SAActionSheetBlock? block;? // 完成Block
?
@end
?
@implementation SAActionSheet
?
+ (instancetype)sheetWithItems:(NSArray<__kindof UIButton *> *)items actionWithBlock:(SAActionSheetBlock)block
{
????SAActionSheet *sheet = [[self alloc] initWithItems:items actionWithBlock:block];
????return [sheet show];
}
?
- (instancetype)initWithItems:(NSArray<__kindof UIButton *> *)items actionWithBlock:(SAActionSheetBlock)block
{
????if (self = [super init]){
????????// 1、接收变量
????????self.block = block;
????????self.items = items;
????????// 2、创建基础面板视图(动画升上来的那个白色面板,用来放分享按钮、标签等)
????????self.baseView = [[UIView alloc] init];
????????self.baseView.backgroundColor = [UIColor colorWithWhite:0.9 alpha:0.9];
????????[self addSubview:self.baseView];
????????// 3、创建分享按钮及对应标签
????????NSMutableArray *labelArray = [NSMutableArray array];
????????for (int i = 0; i < items.count; i++) {
????????????// 3.1、遍历传进来的按钮数组,将每个按钮添加到baseView上,并序号添加tag标记
????????????UIButton *button = [items objectAtIndex:i];
????????????[button setTag:i + 1];
????????????[self.baseView addSubview:button];
????????????// 3.2、创建按钮标签,取出标签后将按钮上的文字删除掉,避免重复
????????????UILabel *label = [[UILabel alloc] init];
????????????label.font = [UIFont systemFontOfSize:11];
????????????label.textAlignment = NSTextAlignmentCenter;
????????????label.text = [button titleForState:UIControlStateNormal];
????????????[labelArray addObject:label];
????????????[self.baseView addSubview:label];
????????????// 3.3、添加按钮事件统一处理方法
????????????[button? setTitle:nil forState:UIControlStateNormal];
????????????[button addTarget:self action:@selector(buttonEven:) forControlEvents:UIControlEventTouchUpInside];
????????}
????????self.labels = labelArray;
????????// 4、取消按钮并绑定相关事件
????????self.cancel = [UIButton buttonWithType:UIButtonTypeSystem];
????????[self.cancel addTarget:self action:@selector(hidden) forControlEvents:UIControlEventTouchUpInside];
????????[self.cancel setBackgroundColor:[UIColor whiteColor]];
????????[self.cancel setTitle:@"取消" forState:UIControlStateNormal];
????????[self.cancel.titleLabel setFont:[UIFont systemFontOfSize:20]];
????????[self.baseView addSubview:self.cancel];
????????// 5、点击空白区域响应取消事件
????????[self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hidden)]];
????}
????return self;
}
/// 视图调整
- (void)layoutSubviews
{
????[super layoutSubviews];
????// SAActionSheet Frame:背景大小
????self.frame = [[UIScreen mainScreen] bounds];
????/* BaseView Frame:基础视图尺寸
?????rows: 为按钮总行数
?????h: baseView视图的高 = (上下间隔高度 + 按钮高度 + 标签高度) * 行数 + 上下间隔高度 + 取消按钮高度
?????w: baseView视图的宽 = 屏幕宽度
?????*/
????NSInteger rows = (self.items.count - 1) / kSAActionSheetItemColumns + 1;
????CGFloat h = rows * (kSAActionSheetItemWidth + kSAActionSheetItemSpace + kSAActionSheetLabelHeight) + kSAActionSheetItemSpace + kSAActionSheetCancelHeight;
????CGFloat w = self.bounds.size.width;
????self.baseView.bounds = CGRectMake(0, 0, self.bounds.size.width, h);
????/* Items Frame:按钮尺寸
?????bw:? 按钮宽度
?????bh:? 按钮高度
?????sp:? 按钮间隔 = (总宽度 - 按钮个数 * 按钮宽度)/ 间隔数
?????*/
????CGFloat bw = kSAActionSheetItemWidth;
????CGFloat bh = kSAActionSheetItemWidth;
????CGFloat sp = (w - bw * kSAActionSheetItemColumns) / (kSAActionSheetItemColumns + 1);
????for (UIButton *button in self.items) {
????????NSInteger index = button.tag;?? // 按钮序号
????????NSInteger row = (index - 1) / kSAActionSheetItemColumns + 1;??? // 行序号
????????NSInteger col = (index - 1) % kSAActionSheetItemColumns + 1;??? // 列序号
????????// 按钮x值、y值
????????CGFloat x = (col - 1) * bw + col * sp;
????????CGFloat y = (row - 1) * (bh + kSAActionSheetLabelHeight) + row * kSAActionSheetItemSpace;
????????button.frame = CGRectMake(x, y, bw, bh);
????????// 在按钮下方设置相对应的标签,宽度与按钮相同,高度为预设定值
????????UILabel *label = [self.labels objectAtIndex:index - 1];
????????label.frame = CGRectMake(x, y + bh, bw, kSAActionSheetLabelHeight);
????}
????// 取消按钮在最下方,高度为50
????self.cancel.frame = CGRectMake(0, h - 50, w, kSAActionSheetCancelHeight);
}
?
/// 显示视图(弹出动画)
- (SAActionSheet *)show
{
????// 1、调整视图大小,添加到当前Windows窗口
????[self layoutSubviews];
????[[[[UIApplication sharedApplication] delegate] window] addSubview:self];
????// 2、将基础视图调整到屏幕最下方、背景设置透明
????CGFloat height = self.bounds.size.height;
????CGFloat w = self.baseView.bounds.size.width;
????CGFloat h = self.baseView.bounds.size.height;
????self.backgroundColor = [UIColor clearColor];
????self.baseView.center = CGPointMake(w * 0.5, height + h * 0.5);
????// 3、执行自下至上的推出及背景变半透明黑的动画
????[UIView animateWithDuration:0.25 animations:^{
????????self.baseView.center = CGPointMake(w * 0.5, height - h * 0.5);
????????self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
????}];
????return self;
}
?
/// 隐藏视图(退出释放)
- (void)hidden
{
????// 按键视图块整体下移至超出屏幕动画,背景变透明,动画结束后将视图从窗口移除
????CGFloat height = self.bounds.size.height;
????CGFloat w = self.baseView.bounds.size.width;
????CGFloat h = self.baseView.bounds.size.height;
????[UIView animateWithDuration:0.35 animations:^{
????????self.baseView.center = CGPointMake(w * 0.5, height + h * 0.5);
????????self.backgroundColor = [UIColor clearColor];
????} completion:^(BOOL finished) {
????????[self removeFromSuperview];
????}];
}
?
/// 按钮事件转交给Block处理
- (void)buttonEven:(UIButton *)button
{
????// 将事件及触发事件的按钮序号转交出去,并取消视图
????if (self.block) self.block(button, button.tag);
????[self hidden];
}
@end

5、Demo下载
SAShare

Leave a Reply