如上图所示,这是一个相当复杂的三级联动界面,如果我们毫无章法的将代码堆积在父视图控制器中,无疑会使控制器变的臃肿,代码的易读性将会很差,不便于日后维护;代码也是一种艺术,我们何不做的优雅一些?
1.思路
为了避免父视图控制器的代码臃肿,降低代码之间的耦合性,此处应采用组件化的设计模式,将控件从控制器中抽离出来,并可以自处业务逻辑,将父视图控制器作为一个纯粹的容器视图,传递数据的中间者;而子控件在被用户交互时通过代理、block回调或者通知将信息传递给父视图控制器,进而父视图控制器做出相应操作;
那么我们首先分析一下这个界面的结构并分析如何抽取其中的控件:
红线标出:
左边的竖向选择列表和右边的数据展示区域都可以抽取成独立的组件,可以用UICollectionView来实现;
蓝线标出:
可以通过在自定义UICollectionViewCell时放置一个UITabelView来实现;
绿线标出:
这个横向的选择列表可以单独抽取出来用UICollectionView实现,并赋值到UITabbleView的headerView;
2.效果演示
写了一个简单的demo,下面是演示效果:
3.�核心代码
父视图添加竖向选择列表和数据展示列表
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.view addSubview:self.displayView];
[self.view addSubview:self.verticalList];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.verticalList mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.mas_equalTo(KMargin);
make.width.mas_equalTo(VerticalListItemWidth);
make.height.mas_equalTo(VerticalListItemWidth * VerticalListItemNumber);
}];
[self.displayView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(KMargin);
make.left.mas_equalTo(self.verticalList.mas_right).offset(20);
make.right.mas_equalTo(-KMargin);
make.bottom.mas_equalTo(-KMargin);
}];
}
//此处可以传递数据
- (VDVerticalList *)verticalList{
if (_verticalList == nil) {
_verticalList = [[VDVerticalList alloc] initWithItemNumber:VerticalListItemNumber ItemWidth:VerticalListItemWidth];
_verticalList.VDVerticalListDelegate = self;
}
return _verticalList;
}
- (VDDisplayView *)displayView{
if (_displayView == nil) {
_displayView = [[VDDisplayView alloc] initWithItemNumber:VerticalListItemNumber ItemSize:CGSizeMake(KMainScreenWidth - VerticalListItemWidth - KMargin * 3, KMainScreenHeight - KMargin * 2)];
}
return _displayView;
}
竖向选择列表通过代理实现点击事件的传递步骤
竖向选择列表声明代理协议和方法:
@protocol VDVerticalListDelegate <NSObject>
- (void)VDVerticalListDidClickItem:(NSIndexPath *)index;
@end
竖向选择列表调用代理方法:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if ([self.VDVerticalListDelegate respondsToSelector:@selector(VDVerticalListDidClickItem:)]) {
[self.VDVerticalListDelegate VDVerticalListDidClickItem:indexPath];
}
}
父视图实现代理方法:
- (void)VDVerticalListDidClickItem:(NSIndexPath *)index {
[self.displayView scrollToItemAtIndexPath:index atScrollPosition:UICollectionViewScrollPositionLeft animated:YES];
}
横向选择列表通过代理实现点击事件的传递步骤
横向选择列表声明代理协议和方法:
@protocol VDCrosswiseListDelegate <NSObject>
- (void)VDCrosswiseListDidClickItem:(NSIndexPath *)index;
@end
横向选择列表调用代理方法:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
if ([self.VDCrosswiseListDelegate respondsToSelector:@selector(VDCrosswiseListDidClickItem:)]) {
[self.VDCrosswiseListDelegate VDCrosswiseListDidClickItem:indexPath];
}
}
UITabelView实现代理方法:
- (void)VDCrosswiseListDidClickItem:(NSIndexPath *)index {
//在此处刷新数据
self.text = [NSString stringWithFormat:@"%zd",index.item];
[self.tableView reloadData];
}
4.源码
源码放在gitHub上,欢迎大家指正,记得�star哦!