forked from b051/RSMenuView
-
Notifications
You must be signed in to change notification settings - Fork 0
/
VHMenuView.m
266 lines (236 loc) · 9.21 KB
/
VHMenuView.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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
//
// VHMenuView.m
//
// Created by Rex Sheng on 10/16/12.
// Copyright (c) 2012 Log(n) LLC. All rights reserved.
//
#import "VHMenuView.h"
#import "VHMenuFoldButton.h"
#import "VHRowBackgroundView.h"
#import "VHMenuCell.h"
NSString * const kVHMenuTitle = @"title";
NSString * const kVHMenuLeftView = @"leftview";
NSString * const kVHMenuRightViews = @"rightviews";
NSString * const kVHMenuItems = @"items";
#pragma mark - VHMenuView
@interface VHMenuView () <UITableViewDataSource, UITableViewDelegate>
@end
@implementation VHMenuView
{
NSMutableDictionary *foldableRows;
NSArray *configuration;
NSMutableArray *currentRows;
UITableView *_tableView;
NSString *selectedIdentifier;
__unsafe_unretained Class cellClass;
}
@synthesize textColor, highlightedTextColor;
@synthesize rowAnimation, rowSize, rowEdgeInsets;
@synthesize delegate;
- (id)initWithFrame:(CGRect)frame
{
return [self initWithFrame:frame cellClass:[VHMenuCell class]];
}
- (id)initWithFrame:(CGRect)frame cellClass:(__unsafe_unretained Class)_cellClass
{
self = [super initWithFrame:frame];
if (self) {
cellClass = _cellClass;
NSAssert([cellClass isSubclassOfClass:[VHMenuCell class]], @"cellClass must be VHMenuCell subclass");
_tableView = [[UITableView alloc] initWithFrame:self.bounds style:UITableViewStylePlain];
_tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self addSubview:_tableView];
_tableView.delegate = self;
textColor = [UIColor whiteColor];
_tableView.dataSource = self;
_tableView.backgroundColor = [UIColor clearColor];
_tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
foldableRows = [NSMutableDictionary dictionary];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(menuFoldingChanged:) name:VHMenuOpenNotification object:nil];
self.rowSize = CGSizeMake(frame.size.width, 44);
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)setRowSize:(CGSize)_rowSize
{
rowSize = _rowSize;
_tableView.rowHeight = rowSize.height;
}
- (void)menuFoldingChanged:(NSNotification *)note
{
id opening = [note.userInfo objectForKey:kVHMenuOpening];
id identifier = [note.userInfo objectForKey:kVHMenuIdentifier];
[foldableRows setObject:opening forKey:identifier];
__block NSDictionary *config = nil;
[configuration enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([[obj objectForKey:kVHMenuIdentifier] isEqualToString:identifier]) {
*stop = YES;
config = obj;
}
}];
NSUInteger startRow = [currentRows indexOfObject:config] + 1;
NSArray *subitems = [config objectForKey:kVHMenuItems];
[_tableView beginUpdates];
if ([opening boolValue]) {
NSMutableArray *indexPaths = [NSMutableArray array];
for (int i = 0; i < subitems.count; i++) {
NSUInteger row = startRow + i;
[currentRows insertObject:subitems[i] atIndex:row];
[indexPaths addObject:[NSIndexPath indexPathForRow:row inSection:0]];
}
[_tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:rowAnimation];
} else {
NSMutableArray *indexPaths = [NSMutableArray array];
[currentRows removeObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(startRow, subitems.count)]];
for (int i = 0; i < subitems.count; i++) {
NSUInteger row = startRow + i;
[indexPaths addObject:[NSIndexPath indexPathForRow:row inSection:0]];
}
[_tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:rowAnimation];
}
[_tableView endUpdates];
}
- (void)loadFromConfiguration:(NSArray *)_configuration
{
[foldableRows removeAllObjects];
configuration = _configuration;
currentRows = [NSMutableArray arrayWithArray:configuration];
[configuration enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSArray *subitems = [obj objectForKey:kVHMenuItems];
NSString *identifier = [obj objectForKey:kVHMenuIdentifier];
if (subitems && identifier) {
BOOL opening = [obj[@"itemsOpened"] boolValue];
[foldableRows setObject:@(opening) forKey:identifier];
if (opening) [currentRows addObjectsFromArray:subitems];
}
}];
[_tableView reloadData];
}
#pragma mark - UITableView Delegate & DataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return currentRows.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = @"VHMenuCell";
VHMenuCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[cellClass alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
CGRect frame = cell.contentView.bounds;
cell.backgroundView = [[VHRowBackgroundView alloc] initWithFrame:frame];
cell.selectedBackgroundView = [[VHRowBackgroundView alloc] initWithFrame:frame];
//imageview
CGFloat r = frame.size.height - rowEdgeInsets.top - rowEdgeInsets.bottom;
cell.imageView.frame = CGRectMake(rowEdgeInsets.left, rowEdgeInsets.top, r, r);
cell.imageView.contentMode = UIViewContentModeCenter;
//textlabel
CGFloat x = r + rowEdgeInsets.left * 2;
cell.textLabel.frame = CGRectMake(x, rowEdgeInsets.top, rowSize.width - rowEdgeInsets.right - x, r);
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.highlightedTextColor = self.highlightedTextColor;
cell.textLabel.shadowOffset = CGSizeMake(0, 1);
//rightview
frame.size.width = rowSize.width;
cell.rightView = [[VHMenuRightView alloc] initWithFrame:cell.textLabel.frame];
cell.rightView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin;
[cell.contentView addSubview:cell.rightView];
}
NSDictionary *row = [currentRows objectAtIndex:indexPath.row];
//indent
NSUInteger indent = [[row objectForKey:@"indent"] integerValue];
if ([self.delegate respondsToSelector:@selector(menuView:fontForTextAtIndent:)]) {
cell.textLabel.font = [self.delegate menuView:self fontForTextAtIndent:indent];
}
[(VHRowBackgroundView *)cell.backgroundView setHighlighted:indent == 0];
//title
cell.textLabel.text = [row objectForKey:@"title"];
//leftviews
NSString *leftview = [row objectForKey:@"leftview"];
if (leftview) {
cell.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%@_active", leftview]];
cell.imageView.highlightedImage = [UIImage imageNamed:[NSString stringWithFormat:@"%@_enabled", leftview]];
} else {
cell.imageView.image = nil;
}
//rightviews
NSArray *subitems = [row objectForKey:kVHMenuItems];
NSArray *rightViewsConfiguration = [row objectForKey:kVHMenuRightViews];
NSString *identifier = [row objectForKey:kVHMenuIdentifier];
NSMutableArray *rightViews = [NSMutableArray array];
if (rightViewsConfiguration) {
for (NSDictionary *config in rightViewsConfiguration) {
id rid = config[kVHMenuIdentifier];
if ([self.delegate respondsToSelector:@selector(menuView:attributesForItemWithIdentifier:)]) {
NSDictionary *attributes = [self.delegate menuView:self attributesForItemWithIdentifier:rid];
if (attributes) {
NSMutableDictionary *r = [config mutableCopy];
[r addEntriesFromDictionary:attributes];
[rightViews addObject:r];
} else {
[rightViews addObject:config];
}
} else {
[rightViews addObject:config];
}
}
}
if (subitems && identifier) {
BOOL opening = [[foldableRows objectForKey:identifier] boolValue];
[rightViews addObject:@{
kVHMenuType: @"VHMenuFoldButton",
kVHMenuIdentifier: identifier,
kVHMenuOpening: @(opening)
}];
}
[cell.rightView loadItems:rightViews];
if ([selectedIdentifier isEqualToString:identifier]) {
[cell setSelected:YES animated:NO];
}
return cell;
}
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *row = [currentRows objectAtIndex:indexPath.row];
NSArray *subitems = [row objectForKey:kVHMenuItems];
NSString *identifier = [row objectForKey:kVHMenuIdentifier];
if (subitems && identifier) {
BOOL opening = ![[foldableRows objectForKey:identifier] boolValue];
[[NSNotificationCenter defaultCenter] postNotificationName:VHMenuOpenNotification
object:nil
userInfo:@{
kVHMenuOpening: @(opening),
kVHMenuIdentifier: identifier}];
return nil;
}
return indexPath;
}
- (void)setItemSelectedWithIdentifier:(NSString *)identifier
{
selectedIdentifier = identifier;
[currentRows enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([obj[kVHMenuIdentifier] isEqualToString:selectedIdentifier]) {
[_tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:idx inSection:0] animated:NO scrollPosition:UITableViewScrollPositionNone];
}
}];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *row = [currentRows objectAtIndex:indexPath.row];
NSString *identifier = [row objectForKey:kVHMenuIdentifier];
if (identifier) {
if ([self.delegate respondsToSelector:@selector(menuView:didSelectedItemWithIdentifier:)]) {
selectedIdentifier = identifier;
[self.delegate menuView:self didSelectedItemWithIdentifier:identifier];
}
}
}
@end