文章转自: http://blog.csdn.net/xunyn/article/details/8567249
官方UIKit下的TableView,支持section和row的显示,但不支持在talbeview里显示多级树型结构的menu,因为项目需要便写了一个支持多级目录显示menu的Demo(下载传送门)。支持菜单展开动画效果,支持级联打开下下级子目录。
效果图如下:
要现实多级目录,首先要做的是在内存构建树型结构,通过这个树型结构,当用户点击了某个有子项的菜单,其变会根据树型结构将menu展开或收起。
下面是“树”中节点的构造,在这里并没有使用CFTree,出于两点考虑:一是menu的结构一般只需知道其子菜单即可,是一个简单应用;第二是项目内部有对C++不了解的童鞋。
#import <Foundation/Foundation.h>
@interface MyItem : NSObject
@property (nonatomic,retain) NSString * title;
@property (nonatomic) NSInteger level;
@property (nonatomic, retain) NSMutableArray *subItems;
@property (nonatomic) BOOL isSubItemOpen;
@property (nonatomic) BOOL isSubCascadeOpen;
@end
其中,subItems这个数组,存放该节点的子菜单,使用isSubItemOpen来标记自菜单是否被打开,使用isCascadeOpen标记该子菜单是否要在其父菜单展开时自动展开。
菜单级联收起代码
#pragma mark -- insert
- (NSArray *)insertMenuIndexPaths:(MyItem *)item
{
NSArray * arr;
[treeItemsToInsert removeAllObjects];
[self insertMenuObject:item];
arr = [self insertIndexsOfMenuObject:treeItemsToInsert];
return arr;
}
- (void) insertMenuObject:(MyItem *)item
{
NSLog(@"%d",[_tableViewData indexOfObject:item]);
if (item == nil)
{
return ;
}
NSIndexPath *path = [NSIndexPath indexPathForRow:[_tableViewData indexOfObject:item] inSection:0];
MyItem *childItem;
for (int i = 0; i<[item.subItems count] ; i++) {
childItem = [item.subItems objectAtIndex:i];
[_tableViewData insertObject:childItem atIndex:path.row + i +1];
[treeItemsToInsert addObject:childItem];
item.isSubItemOpen = YES;
}
for (int i = 0; i <[item.subItems count]; i ++) {
childItem = [item.subItems objectAtIndex:i];
if (childItem .isSubCascadeOpen) {
[self insertMenuObject:childItem];
}
}
return ;
}
- (NSArray *) insertIndexsOfMenuObject :(NSMutableArray *) array
{
NSMutableArray * mutableArr;
mutableArr = [NSMutableArray array];
for (MyItem * item in array) {
NSIndexPath *path = [NSIndexPath indexPathForRow:[_tableViewData indexOfObject:item] inSection:0];
[mutableArr addObject:path];
}
return mutableArr;
}
其中使用insertMenuObject函数的递归调用,来完成对item子树的遍历
在tableViewController里逻辑要尽量简单,其中在tableView:didSelectRowAtIndexPath里代码如下
<pre name="code" class="cpp"> MenuItemCell * cell;
cell = (MenuItemCell *)[tableView cellForRowAtIndexPath:indexPath];
if (cell.item.isSubItemOpen)
{
//remove
NSArray * arr;
arr = [_menuData deleteMenuIndexPaths:cell.item];
if ([arr count] >0) {
[tableView deleteRowsAtIndexPaths: arr withRowAnimation:UITableViewRowAnimationBottom];
}
}
else
{
//insert
NSArray * arr;
arr = [_menuData insertMenuIndexPaths:cell.item];
if ([arr count] >0) {
[tableView insertRowsAtIndexPaths:arr withRowAnimation:UITableViewRowAnimationBottom];
}
}</pre><br>
<br>
<pre></pre>
<span style="font-size:14px">其中,cell的插入和移除的动画,使用<span style="font-family:Menlo"></span>withRowAnimation完成。</span>
<p></p>
<p><span style="font-family:Menlo"><span style="font-size:20px"><br>
</span></span><br>
<br>
<br>
</p>
<p><span style="font-size:18px"><br>
</span></p>