一:在ios项目实际开发中经常会看到级联菜单的效果:如图:点击左侧菜单,右侧菜单刷新数据。此篇用两个tableView来实现如图效果:
二:代码:
1:构造数据模型:利用kvc快速构建数据模型
1 #import2 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 ()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 - 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];