官方UIKit下的TableView,支持section和row的显示,但不支持在talbeview里显示多级树型结构的menu,因为项目需要便写了一个支持多级目录显示menu的Demo(下载传送门)。支持菜单展开动画效果,支持级联打开下下级子目录。
效果图如下:
要现实多级目录,首先要做的是在内存构建树型结构,通过这个树型结构,当用户点击了某个有子项的菜单,其变会根据树型结构将menu展开或收起。
下面是“树”中节点的构造,在这里并没有使用CFTree,出于两点考虑:一是menu的结构一般只需知道其子菜单即可,是一个简单应用;第二是项目内部对C 不了的童鞋。
-
@interface MyItem : NSObject
-
@property (nonatomic,retain) NSString * title;
-
@property (nonatomic) NSInteger level;
-
@property (nonatomic, retain) NSMutableArray *subItems;
-
@property (nonatomic) BOOL isSubItemOpen;
-
@property (nonatomic) BOOL isCascadeOpen;
-
@end
其中,subItems这个数组,存放该节点的子菜单,使用isSubItemOpen来标记自菜单是否被打开,使用isCascadeOpen标记该子菜单是否要在其父菜单展开时自动展开。
菜单级联收起代码
-
- (NSMutableArray *) cascadingDeletePaths:(NSIndexPath *)indexPath
-
{
-
[treeItemsToRemove removeAllObjects];
-
MyItem * item;
-
item = [_tableViewData objectAtIndex:indexPath.row];
-
-
[self cascadingDeleteCellPaths:item];
-
-
NSMutableIndexSet * set;
-
set = [NSMutableIndexSet indexSet];
-
for (int i = 0; i < [treeItemsToRemove count]; i ) {
-
NSIndexPath *index;
-
index = [treeItemsToRemove objectAtIndex:i];
-
[set addIndex:index.row];
-
}
-
item.isSubItemOpen = NO;
-
[_tableViewData removeObjectsAtIndexes:set];
-
return treeItemsToRemove;
-
}
-
- (void) cascadingDeleteCellPaths:(MyItem *)item
-
{
-
-
for (int i = 0; i < [item.subItems count] && item.isSubItemOpen ; i ) {
-
MyItem * item1;
-
item1 = [item.subItems objectAtIndex:i];
-
NSLog(@'sub %@',item1);
-
-
NSIndexPath *path = [NSIndexPath indexPathForRow:[_tableViewData indexOfObject:item1] inSection:0];
-
-
[self cascadingDeleteCellPaths:item1];
-
[treeItemsToRemove addObject:path];
-
item1.isSubItemOpen = NO;
-
}
-
}
其中使用cascadingDeleteCellPaths函数的递归调用,来完成对item子树的遍历。
在tableViewController里逻辑要尽量简单,其中在tableView:didSelectRowAtIndexPath里代码如下
-
MenuItemCell * cell;
-
cell = (MenuItemCell *)[tableView cellForRowAtIndexPath:indexPath];
-
if (cell.item.isSubItemOpen)
-
{
-
//remove
-
NSArray * arr;
-
arr = [_menuData cascadingDeletePaths:indexPath];
-
if ([arr count] >0) {
-
[tableView deleteRowsAtIndexPaths: arr withRowAnimation:UITableViewRowAnimationBottom];
-
}
-
}
-
else
-
{
-
//insert
-
NSArray * arr;
-
arr = [_menuData cascadingInsertCellPaths:indexPath];
-
if ([arr count] >0) {
-
[tableView insertRowsAtIndexPaths:arr withRowAnimation:UITableViewRowAnimationBottom];
-
}
-
}
其中,cell的插入和移除的动画,使用withRowAnimation完成。
|