iOS 类似QQ的popMenu

.h

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
@interface QQPopMenuView : UIView

@property (nonatomic, copy) void (^hideHandle)();

/**
* 实例化方法
*
* @param array items,包含字典,字典里面包含标题(title)、图片名(imageName)
* @param width 宽度
* @param point 三角的顶角坐标(基于window)
* @param action 点击回调
*/
- (instancetype)initWithItems:(NSArray <NSDictionary *>*)array
width:(CGFloat)width
triangleLocation:(CGPoint)point
action:(void(^)(NSInteger index))action;

/**
* 类方法展示
*
* @param array items,包含字典,字典里面包含标题(title)、图片名(imageName)
* @param width 宽度
* @param point 三角的顶角坐标(基于window)
* @param action 点击回调
*/
+ (void)showWithItems:(NSArray <NSDictionary *>*)array
width:(CGFloat)width
triangleLocation:(CGPoint)point
action:(void(^)(NSInteger index))action;

- (void)show;
- (void)hide;

@end

.m

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
#import "QQPopMenuView.h"
#import "PopMenuTableViewCell.h"

#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width

static CGFloat const kCellHeight = 44;

@interface QQPopMenuView ()<UITableViewDelegate,UITableViewDataSource,UIGestureRecognizerDelegate>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSArray *tableData;
@property (nonatomic, assign) CGPoint trianglePoint;
@property (nonatomic, copy) void(^action)(NSInteger index);
@end

@implementation QQPopMenuView

- (instancetype)initWithItems:(NSArray <NSDictionary *>*)array
width:(CGFloat)width
triangleLocation:(CGPoint)point
action:(void(^)(NSInteger index))action
{
if (array.count == 0) {
return nil;
}

if (self = [super init]) {
self.frame = [UIScreen mainScreen].bounds;
self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.2];
self.alpha = 0;
_tableData = [array copy];
_trianglePoint = point;
self.action = action;


// 添加手势
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
tap.delegate = self;
[self addGestureRecognizer:tap];


// 创建tableView
_tableView = [[UITableView alloc] initWithFrame:CGRectMake(SCREEN_WIDTH - width - 5, point.y + 10, width, kCellHeight * array.count) style:UITableViewStylePlain];
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.layer.masksToBounds = YES;
_tableView.layer.cornerRadius = 5;
_tableView.scrollEnabled = NO;
_tableView.rowHeight = kCellHeight;
[_tableView registerNib:[UINib nibWithNibName:@"PopMenuTableViewCell" bundle:nil] forCellReuseIdentifier:@"PopMenuTableViewCell"];
[self addSubview:_tableView];

}
return self;
}

+ (void)showWithItems:(NSArray <NSDictionary *>*)array
width:(CGFloat)width
triangleLocation:(CGPoint)point
action:(void(^)(NSInteger index))action
{
QQPopMenuView *view = [[QQPopMenuView alloc] initWithItems:array width:width triangleLocation:point action:action];
[view show];
}

- (void)tap {
[self hide];
}

#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:NSClassFromString(@"UITableViewCellContentView")]) {
return NO;
}
return YES;
}

#pragma mark - Show or Hide
- (void)show {
[[UIApplication sharedApplication].keyWindow addSubview:self];
// 设置右上角为transform的起点(默认是中心点)
_tableView.layer.position = CGPointMake(SCREEN_WIDTH - 5, _trianglePoint.y + 10);
// 向右下transform
_tableView.layer.anchorPoint = CGPointMake(1, 0);
_tableView.transform = CGAffineTransformMakeScale(0.0001, 0.0001);
[UIView animateWithDuration:0.2 animations:^{
self.alpha = 1;
_tableView.transform = CGAffineTransformMakeScale(1.0, 1.0);
}];
}

- (void)hide {
[UIView animateWithDuration:0.2 animations:^{
self.alpha = 0;
_tableView.transform = CGAffineTransformMakeScale(0.0001, 0.0001);
} completion:^(BOOL finished) {
[_tableView removeFromSuperview];
[self removeFromSuperview];
if (self.hideHandle) {
self.hideHandle();
}
}];
}

#pragma mark - Draw triangle
- (void)drawRect:(CGRect)rect {
// 设置背景色
[[UIColor whiteColor] set];
//拿到当前视图准备好的画板
CGContextRef context = UIGraphicsGetCurrentContext();
//利用path进行绘制三角形
CGContextBeginPath(context);
CGPoint point = _trianglePoint;
// 设置起点
CGContextMoveToPoint(context, point.x, point.y);
// 画线
CGContextAddLineToPoint(context, point.x - 10, point.y + 10);
CGContextAddLineToPoint(context, point.x + 10, point.y + 10);
CGContextClosePath(context);
// 设置填充色
[[UIColor whiteColor] setFill];
// 设置边框颜色
[[UIColor whiteColor] setStroke];
// 绘制路径
CGContextDrawPath(context, kCGPathFillStroke);
}

#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.tableData.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
PopMenuTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"PopMenuTableViewCell" forIndexPath:indexPath];
NSDictionary *dic = _tableData[indexPath.row];
cell.leftImageView.image = [UIImage imageNamed:dic[@"imageName"]];
cell.titleLabel.text = dic[@"title"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.layoutMargins = UIEdgeInsetsZero;
cell.separatorInset = UIEdgeInsetsZero;
return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self hide];
if (_action) {
_action(indexPath.row);
}
}

@end

调用

1
2
3
4
5
6
7
8
9
[QQPopMenuView showWithItems:@[@{@"title":@"发起讨论",@"imageName":@"popMenu_createChat"},
@{@"title":@"扫描名片",@"imageName":@"popMenu_scanCard"},
@{@"title":@"写日报",@"imageName":@"popMenu_writeReport"},
@{@"title":@"外勤签到",@"imageName":@"popMenu_signIn"}]
width:130
triangleLocation:CGPointMake([UIScreen mainScreen].bounds.size.width-30, 64+5)
action:^(NSInteger index) {
NSLog(@"点击了第%ld行",index);
}];

效果图

screenshot.gif

Demo

https://github.com/guanzhendong/QQPopMenuView


iOS 类似QQ的popMenu
http://example.com/2016/07/01/iOS-类似QQ的popMenu/
作者
guanzhendong
发布于
2016年7月1日
许可协议