一、简介
如果2个控制器的view是父子关系(不管是直接还是间接的父子关系),那么这2个控制器也应该为父子关系。这样不至于控制器死了,它的view还没有销毁。
// 通过addChildViewController添加的控制器都会存在于childViewControllers数组中
[self addChildViewController:[[XMGOneViewController alloc] init]];
[self addChildViewController:[[XMGTwoViewController alloc] init]];
[self addChildViewController:[[XMGThreeViewController alloc] init]];
// 将XMGOneViewController从childViewControllers数组中移除
// [self.childViewControllers[0] removeFromParentViewController];
}
- (IBAction)buttonClick:(UIButton *)button {
// 移除其他控制器的view
[self.showingVc.view removeFromSuperview];
// 获得控制器的位置(索引)
NSUInteger index = [button.superview.subviews indexOfObject:button];
// 添加控制器的view
self.showingVc = self.childViewControllers[index];
self.showingVc.view.frame = CGRectMake(0, 64, self.view.frame.size.width, self.view.frame.size.height - 64);
[self.view addSubview:self.showingVc.view];
}
二、带动画效果的
#import "ViewController.h"
#import "XMGOneViewController.h"
#import "XMGTwoViewController.h"
#import "XMGThreeViewController.h"
@interface ViewController ()
/** 正在显示的控制器 */
@property (nonatomic, weak) UIViewController *showingVc;
/** 用来存放子控制器的view */
@property (nonatomic, weak) UIView *contentView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIView *contentView = [[UIView alloc] init];
contentView.frame = CGRectMake(0, 64, self.view.frame.size.width, self.view.frame.size.height - 64);
[self.view addSubview:contentView];
self.contentView = contentView;
[self addChildViewController:[[XMGOneViewController alloc] init]];
// [self.childViewControllers[0] didMoveToParentViewController:self];
[self addChildViewController:[[XMGTwoViewController alloc] init]];
[self addChildViewController:[[XMGThreeViewController alloc] init]];
// 当一个控制器从父控制器中移除时。会自动调用控制器的didMoveToParentViewController:方法,并且参数是nil
// [self.childViewControllers[0] removeFromParentViewController];
}
- (IBAction)buttonClick:(UIButton *)button {
// 移除其他控制器的view
[self.showingVc.view removeFromSuperview];
// 获得控制器的位置(索引)
NSUInteger index = [button.superview.subviews indexOfObject:button];
// 当前控制器的索引
NSUInteger oldIndex = [self.childViewControllers indexOfObject:self.showingVc];
// 添加控制器的view
self.showingVc = self.childViewControllers[index];
self.showingVc.view.frame = self.contentView.bounds;
[self.contentView addSubview:self.showingVc.view];
// 动画
CATransition *animation = [CATransition animation];
animation.type = @"cube";
animation.subtype = index > oldIndex ? kCATransitionFromRight : kCATransitionFromLeft;
animation.duration = 0.5;
[self.contentView.layer addAnimation:animation forKey:nil];
}
三、回调方法
/**
* 当前控制器已经被添加到某个父控制器上时就会调用这个方法
*/
- (void)didMoveToParentViewController:(UIViewController *)parent
{
[super didMoveToParentViewController:parent];
NSLog(@"didMoveToParentViewController - %@", parent);
}
四、级联菜单的两种实现方式
方式一:在一个控制器里实现
#import "ViewController.h"
#import "XMGCategory.h"
@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
/** 右边表格 */
@property (weak, nonatomic) IBOutlet UITableView *subcategoryTableView;
/** 左边表格 */
@property (weak, nonatomic) IBOutlet UITableView *categoryTableView;
/** 所有的类别数据 */
@property (nonatomic, strong) NSArray *categories;
@end
@implementation ViewController
- (NSArray *)categories
{
if (_categories == nil) {
NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"categories" ofType:@"plist"]];
NSMutableArray *categoryArray = [NSMutableArray array];
for (NSDictionary *dict in dictArray) {
[categoryArray addObject:[XMGCategory categoryWithDict:dict]];
}
_categories = categoryArray;
}
return _categories;
}
- (void)viewDidLoad {
[super viewDidLoad];
// 不会自动去调整uiscrollView的contentInset属性
// self.automaticallyAdjustsScrollViewInsets = NO;
// 默认选中左边表格的第0行
[self.categoryTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:NO scrollPosition:UITableViewScrollPositionTop];
self.subcategoryTableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (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;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// 左边表格
if (tableView == self.categoryTableView) {
static NSString *ID = @"category";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
XMGCategory *c = self.categories[indexPath.row];
// 设置普通图片
cell.imageView.image = [UIImage imageNamed:c.icon];
// 设置高亮图片(cell选中 -> cell.imageView.highlighted = YES -> cell.imageView显示highlightedImage这个图片)
cell.imageView.highlightedImage = [UIImage imageNamed:c.highlighted_icon];
// 设置label高亮时的文字颜色
cell.textLabel.highlightedTextColor = [UIColor redColor];
cell.textLabel.text = c.name;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
} else {
// 右边表格
static NSString *ID = @"subcategory";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 获得左边表格被选中的模型
XMGCategory *c = self.categories[self.categoryTableView.indexPathForSelectedRow.row];
cell.textLabel.text = c.subcategories[indexPath.row];
return cell;
}
}
#pragma mark - <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.categoryTableView) {
[self.subcategoryTableView reloadData];
}
}
@end
方式二:用父子控制器
1.父控制器
#import "ViewController.h"
#import "XMGCategoryViewController.h"
#import "XMGSubcategoryViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
CGFloat width = self.view.frame.size.width * 0.5;
CGFloat height = self.view.frame.size.height;
XMGSubcategoryViewController *subcategoryVc = [[XMGSubcategoryViewController alloc] init];
subcategoryVc.view.frame = CGRectMake(width, 0, width, height);
[self addChildViewController:subcategoryVc];
[self.view addSubview:subcategoryVc.view];
XMGCategoryViewController *categoryVc = [[XMGCategoryViewController alloc] init];
categoryVc.delegate = subcategoryVc;
categoryVc.view.frame = CGRectMake(0, 0, width, height);
[self addChildViewController:categoryVc];
[self.view addSubview:categoryVc.view];
}
@end
2.子控制器一
#import <UIKit/UIKit.h>
@class XMGCategoryViewController;
@protocol XMGCategoryViewControllerDelegate <NSObject>
@optional
- (void)categoryViewController:(XMGCategoryViewController *)categoryViewController didSelectSubcategories:(NSArray *)subcategories;
@end
@interface XMGCategoryViewController : UITableViewController
@property (nonatomic, weak) id<XMGCategoryViewControllerDelegate> delegate;
@end
#import "XMGCategoryViewController.h"
#import "XMGCategory.h"
@interface XMGCategoryViewController ()
/** 所有的类别数据 */
@property (nonatomic, strong) NSArray *categories;
@end
@implementation XMGCategoryViewController
- (NSArray *)categories
{
if (_categories == nil) {
NSArray *dictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"categories" ofType:@"plist"]];
NSMutableArray *categoryArray = [NSMutableArray array];
for (NSDictionary *dict in dictArray) {
[categoryArray addObject:[XMGCategory categoryWithDict:dict]];
}
_categories = categoryArray;
}
return _categories;
}
static NSString *categoryID = @"category";
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:categoryID];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.categories.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:categoryID];
XMGCategory *c = self.categories[indexPath.row];
// 设置普通图片
cell.imageView.image = [UIImage imageNamed:c.icon];
// 设置高亮图片(cell选中 -> cell.imageView.highlighted = YES -> cell.imageView显示highlightedImage这个图片)
cell.imageView.highlightedImage = [UIImage imageNamed:c.highlighted_icon];
// 设置label高亮时的文字颜色
cell.textLabel.highlightedTextColor = [UIColor redColor];
cell.textLabel.text = c.name;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
#pragma mark - <代理方法>
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// 告诉代理
if ([self.delegate respondsToSelector:@selector(categoryViewController:didSelectSubcategories:)]) {
XMGCategory *c = self.categories[indexPath.row];
[self.delegate categoryViewController:self didSelectSubcategories:c.subcategories];
}
}
// 当一个cell被选中的时候,cell内部的子控件都会达到highlighted状态
@end
3.子控制器2
#import <UIKit/UIKit.h>
#import "XMGCategoryViewController.h"
@interface XMGSubcategoryViewController : UITableViewController
<XMGCategoryViewControllerDelegate>
@end
#import "XMGSubcategoryViewController.h"
@interface XMGSubcategoryViewController ()
/** 子类别数据 */
@property (nonatomic, strong) NSArray *subcategories;
@end
@implementation XMGSubcategoryViewController
static NSString *subcategoryID = @"subcategory";
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:subcategoryID];
}
#pragma mark - <XMGCategoryViewControllerDelegate>
- (void)categoryViewController:(XMGCategoryViewController *)categoryViewController didSelectSubcategories:(NSArray *)subcategories
{
self.subcategories = subcategories;
[self.tableView reloadData];
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.subcategories.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:subcategoryID];
cell.textLabel.text = self.subcategories[indexPath.row];
return cell;
}
@end