一:在ios項目實際開發中經常會看到級聯菜單的效果:如圖:點擊左側菜單,右側菜單刷新數據。此篇用兩個tableView來實現如圖效果:
二:代碼:
1:構造數據模型:利用kvc快速構建數據模型
1 #import <Foundation/Foundation.h> 2 3 @interface XMGCategory : NSObject 4 /** 子類別 */ 5 @property (nonatomic, strong) NSArray *subcategories; 6 /** 姓名 */ 7 @property (nonatomic, strong) NSString *name; 8 /** 圖標 */ 9 @property (nonatomic, strong) NSString *icon; 10 /** 高亮圖標 */ 11 @property (nonatomic, strong) NSString *highlighted_icon; 12 13 + (instancetype)categoryWithDict:(NSDictionary *)dict; 14 @end
1 #import "XMGCategory.h" 2 3 @implementation XMGCategory 4 + (instancetype)categoryWithDict:(NSDictionary *)dict 5 { 6 XMGCategory *c = [[self alloc] init]; 7 [c setValuesForKeysWithDictionary:dict]; 8 return c; 9 } 10 @end
2:控制器代碼實現:
1 #import "ViewController.h" 2 #import "XMGCategory.h" 3 4 @interface ViewController () <UITableViewDataSource, UITableViewDelegate> 5 /** 右邊表格 */ 6 @property (weak, nonatomic) IBOutlet UITableView *subcategoryTableView; 7 /** 左邊表格 */ 8 @property (weak, nonatomic) IBOutlet UITableView *categoryTableView; 9 /** 所有的類別數據 */ 10 @property (nonatomic, strong) NSArray *categories; 11 @end 12 13 @implementation ViewController 14 15 #pragma mark -- 懶加載數據源 16 - (NSArray *)categories 17 { 18 if (!_categories) { 19 //1:從plist文件中讀取數據 20 NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"categories" ofType:@"plist"]]; 21 //2:構造數據源 22 NSMutableArray *categoryArray = [NSMutableArray array]; 23 for (NSDictionary *dict in dictArray) { 24 [categoryArray addObject:[XMGCategory categoryWithDict:dict]]; 25 } 26 27 //3:賦值數據源 28 _categories = categoryArray; 29 } 30 return _categories; 31 } 32 33 - (void)viewDidLoad { 34 [super viewDidLoad]; 35 36 //1:默認選中左邊表格的第0行 37 [self.categoryTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:NO scrollPosition:UITableViewScrollPositionTop]; 38 39 //2:給右側的tableView增加額外的滾動區域:在有導航欄的時候,系統默認會為UIScrollView或是繼承它的子控件默認增加64的額外滾動區域,如果有兩個繼承於UIScrollView的子控件,則系統默認只會為第一個添加到視圖上的子控件增加額外的滾動區域。如果想禁止,則實現UIScrollView或是tableView等的ContentInset屬性,增加額外的滾動區域,或是在控制器中實現self.automaticallyAdjustsScrollViewInsets = NO; 40 self.subcategoryTableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0); 41 } 42 43 - (void)viewDidAppear:(BOOL)animated 44 { 45 [super viewDidAppear:animated]; 46 47 NSLog(@"categoryTableView - %@", NSStringFromUIEdgeInsets(self.categoryTableView.contentInset)); 48 NSLog(@"subcategoryTableView - %@", NSStringFromUIEdgeInsets(self.subcategoryTableView.contentInset)); 49 } 50 51 #pragma mark - Table view data source 52 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 53 // 左邊表格 54 if (tableView == self.categoryTableView) return self.categories.count; 55 56 // 右邊表格 57 XMGCategory *c = self.categories[self.categoryTableView.indexPathForSelectedRow.row]; 58 return c.subcategories.count; 59 } 60 61 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 62 // 左邊表格 63 if (tableView == self.categoryTableView) { 64 static NSString *ID = @"category"; 65 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; 66 67 XMGCategory *c = self.categories[indexPath.row]; 68 69 // 設置普通圖片 70 cell.imageView.image = [UIImage imageNamed:c.icon]; 71 // 設置高亮圖片(cell選中 -> cell.imageView.highlighted = YES -> cell.imageView顯示highlightedImage這個圖片) 72 cell.imageView.highlightedImage = [UIImage imageNamed:c.highlighted_icon]; 73 74 // 設置label高亮時的文字顏色 75 cell.textLabel.highlightedTextColor = [UIColor redColor]; 76 77 cell.textLabel.text = c.name; 78 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 79 80 return cell; 81 } else { 82 // 右邊表格 83 static NSString *ID = @"subcategory"; 84 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; 85 86 // 獲得左邊表格被選中的模型 87 XMGCategory *c = self.categories[self.categoryTableView.indexPathForSelectedRow.row]; 88 cell.textLabel.text = c.subcategories[indexPath.row]; 89 90 return cell; 91 } 92 } 93 94 #pragma mark - <UITableViewDelegate> 95 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 96 { 97 if (tableView == self.categoryTableView) { 98 [self.subcategoryTableView reloadData]; 99 } 100 }
三:知識點總結:
1:級聯菜單數據模型的設計:1:左側表格數據模型中含有右側表格的數據模型,在定義數據模型時,可用類方法,或是實例方法:類方法實現:alloc創建對象,對象調用KVC快速為屬性賦值,利用KVC必須滿足屬性一一對應,不能少也不多
+ (instancetype)categoryWithDict:(NSDictionary *)dict
{
XMGCategory *c = [[self alloc] init];
[c setValuesForKeysWithDictionary:dict];
return c;
}
2:在構造數據源時:要看清plist根節點是數組還是字典:一般自定義plist數據模型時時,最外層為數組,數組為每一個數據模型的字典:數據源,采用懶加載,懶加載保證只初始化一次,且不用關心何時創建也就是不用考慮代碼順序。從plist中讀取數據:
NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"categories" ofType:@"plist"]];
因為懶加載時,數據源本身就沒有初始化,不存在,所以用
_categories = categoryArray;來對數據源進行賦值,若是初始化了,則可以addObjectFromeArray,或是插入數據:insetObject atIndexSets
3:tableView默認選中某一行:
//1:默認選中左邊表格的第0行
[self.categoryTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:NO scrollPosition:UITableViewScrollPositionTop];
4:給UIscrollView,tableView,UICollectionView增加額外的滾動區域調用:contentInset.
給右側的tableView增加額外的滾動區域:在有導航欄的時候,系統默認會為UIScrollView或是繼承它的子控件默認增加64的額外滾動區域,如果有兩個繼承於UIScrollView的子控件,則系統默認只會為第一個添加到視圖上的子控件增加額外的滾動區域。如果想禁止,則實現UIScrollView或是tableView等的ContentInset屬性,增加額外的滾動區域,或是在控制器中實現self.automaticallyAdjustsScrollViewInsets = NO;
self.subcategoryTableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);
5:在方法
- (void)viewDidAppear:(BOOL)animated里視圖已經出現,在此方法中,也就是視圖出現的時候,能正確打印,調試,或是對控件進行一些設置
6:兩個tableView,在實現數據源或是代理方法時,要區分不同的tableView:如:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// 左邊表格
if (tableView == self.categoryTableView) return self.categories.count;
// 右邊表格
XMGCategory *c = self.categories[self.categoryTableView.indexPathForSelectedRow.row];
return c.subcategories.count;
}
其中,self.categoryTableView.indexPathForSelectedRow,得到的是當前表格選中的indexPath區域
7:UITableViewCell:當某個cell被選中時,系統會默認顯示cell中控件高亮時的狀態,取消選中時,顯示常態:可以設置cell中的UIimageView,lable高亮時的狀態:
//1: 設置普通圖片
cell.imageView.image = [UIImage imageNamed:c.icon];
// 設置高亮圖片(cell選中 -> cell.imageView.highlighted = YES -> cell.imageView顯示highlightedImage這個圖片)
cell.imageView.highlightedImage = [UIImage imageNamed:c.highlighted_icon];
// 2:設置label高亮時的文字顏色
cell.textLabel.highlightedTextColor = [UIColor redColor];