官方UIKit下的TableView,支持section和row的显示,但不支持在talbeview里显示多级树型结构的menu,因为项目需要便写了一个支持多级目录显示menu的Demo(下载传送门)。支持菜单展开动画效果,支持级联打开下下级子目录。
其中,subItems这个数组,存放该节点的子菜单,使用isSubItemOpen来标记自菜单是否被打开,使用isCascadeOpen标记该子菜单是否要在其父菜单展开时自动展开。
其中使用cascadingDeleteCellPaths函数的递归调用,来完成对item子树的遍历。
其中,cell的插入和移除的动画,使用withRowAnimation完成。
效果图如下:
要现实多级目录,首先要做的是在内存构建树型结构,通过这个树型结构,当用户点击了某个有子项的菜单,其变会根据树型结构将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
菜单级联收起代码
- - (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;
- }
- }
在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完成。