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#"];
}