1.将需要显示的视图封装到一个容器视图中,然后在容器视图中填充内容,传递事件。 2. 控制器负责得到数据,传递给视图让其显示 3. 数据被封装为数据模型类 底部导航栏封装我们先要明白的是 视图的层次逻辑关系还有思路。 1.底部导航栏是需要封装的,而且其中的视图需要能接收点击事件,来完成切换界面 2.当切换界面时,我们是否需要将视图的层次调整来达到导航栏一直在最上层的目的 3.多个界面的UI逻辑类似,内容不同,我们只需要给一个界面传递不同的内容,来实现界面切换,视图内容也变化? 首先滤清了这样的思路,也提出了这样的思路是否可以的疑问。下面就开始实现了。 1. 首先封装一个底部导航栏视图。 ** * 与系统导航栏导航实现原理类似 */ #pragma mark - 初始化 + (CustomTabbar *)tabbar { return [[[self class] alloc] init]; } + (CustomTabbar *)tabbarWithTabbarBlock:(myBlock)myBlock { CustomTabbar *tabbar = [CustomTabbar tabbar]; tabbar.tabbarBlock = myBlock; return tabbar; } #pragma mark - 系统方法 用来设置frame - (void)willMoveToSuperview:(UIView *)newSuperview { self.frame = CGRectMake(0, newSuperview.height-49, newSuperview.width, 49); self.backgroundColor = [UIColor lightGrayColor]; } #pragma mark - 逻辑辅助功能 - (void)setBtnTitles:(NSArray *)btnTitles { _btnTitles = btnTitles; CGFloat btnW = self.width/btnTitles.count; NSArray *images = @[@"upomp_button_keyboard3",@"upomp_button_keyboard3_highlighted"]; for (int i = 0; i < btnTitles.count; i++) { UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; [self addSubview:btn]; [self configButton:btn Image:images[0] selectedImage:images[1] title:btnTitles[i]]; btn.frame = CGRectMake(i*btnW, 0, btnW, self.height); btn.tag = i; [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside]; } [self btnClick:(UIButton *)[self.subviews objectAtIndex:0]]; } - (void)configButton:(UIButton *)button Image:(NSString *)imageName selectedImage:(NSString *)selectedIamgeName title:(NSString *)title { [button setTitle:title forState:UIControlStateNormal]; [button setBackgroundImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal]; [button setBackgroundImage:[UIImage imageNamed:selectedIamgeName] forState:UIControlStateSelected]; } #pragma mark - 按钮响应事件 - (void)btnClick:(UIButton *)button { if (button.selected == YES) { return; } for (UIButton *button in self.subviews) { button.selected = NO; } button.selected = YES; self.tabbarBlock(self,button,button.tag); } 1 我们将button封装到自定义容器视图上,并且将会通过block或者代理 将要完成的事情交给控制器来处理。 2 在 视图被添加到父视图的时候,设置frame。这样我们的逻辑十分清晰。 3. 当视图接收到数据,我们将传过来的数据 来开始搭建UI,这就是所谓的逻辑辅助。一般在外部接口方法中实现,也就是setter方法。
容器视图的封装比较简单。 1. 将数据显示 2. 完成类的交互 类的交互 可以用block或者代理 1. block <1. ① 在类内部声明一个block属性作为外部接口 ② 在类的外部定义block代码块。即类的实例变量.block = .. 即让block属性找到block的地址 ③ 在类内部可以随时调用,完成回调功能。 <2. ① 可以在方法中加入block参数 ② 在类内部用block属性接收这个block参数 或是直接调用block代码块 ③ 这个block参数如果被接收不被立即调用。可以选择在其他的时机调用,完成回调。 代理这里先不说了。
因为只有一个容器视图,我们需要点击底部导航栏,来完成切换界面,显示不同的数据和界面。 所以 容器视图如果被更新 即 界面切换,需要释放 然后重新加载。 - (void)viewDidLoad { [super viewDidLoad]; CustomTabbar *tabbar = [CustomTabbar tabbarWithTabbarBlock:^(CustomTabbar *tabbar, UIButton *button, NSInteger index) { // 释放之前的对象 [_contentView removeFromSuperview]; YXContentView *contentView = [YXContentView contentView]; _contentView = contentView; [self.view addSubview:_contentView]; // 给予数据 _contentView.dataArray = self.dataArray[index]; // 调换位置,达到显示的效果 [self.view bringSubviewToFront:_contentView]; [self.view bringSubviewToFront:tabbar]; [_contentView setMyBlock:^(YXContentView *contentView,UIButton *button,NSInteger index) { if (index >= 100) { index -= 100; NSLog(@"%@",[contentView.dataArray[index] valueForKey:@"price"]); } else NSLog(@"%@",[contentView.dataArray[index] valueForKey:@"icon"]); }]; }]; [self.view addSubview:tabbar]; tabbar.btnTitles = @[@"OC",@"JAVA",@"C#"]; }