使用TableView實現多級樹型menu
阿新 • • 發佈:2019-02-02
官方UIKit下的TableView,支援section和row的顯示,但不支援在talbeview裡顯示多級樹型結構的menu,因為專案需要便寫了一個支援多級目錄顯示menu的Demo(下載傳送門)。支援選單展開動畫效果,支援級聯開啟下下級子目錄。
其中,subItems這個陣列,存放該節點的子選單,使用isSubItemOpen來標記自選單是否被開啟,使用isCascadeOpen標記該子選單是否要在其父選單展開時自動展開。
其中使用insertMenuObject函式的遞迴呼叫,來完成對item子樹的遍歷
其中,cell的插入和移除的動畫,使用withRowAnimation完成。
效果圖如下:
要現實多級目錄,首先要做的是在記憶體構建樹型結構,通過這個樹型結構,當用戶點選了某個有子項的選單,其變會根據樹型結構將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裡程式碼如下
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]; } }
其中,cell的插入和移除的動畫,使用withRowAnimation完成。