两个tableView的联动梳理清晰了逻辑之后,实现起来其实很简单。

- 设置正确的数据结构

NSString *path = [[NSBundle mainBundle] pathForResource:@"meituan" ofType:@"json"];
NSData *data = [NSData dataWithContentsOfFile:path];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSArray *foods = dict[@"data"][@"food_spu_tags"];
for (NSDictionary *dict in foods) {
CategoryModel *model = [CategoryModel objectWithDictionary:dict];
#左侧-------tableView的数据源
[self.categoryData addObject:model];
NSMutableArray *datas = [NSMutableArray array];
for (FoodModel *f_model in model.spus) {
[datas addObject:f_model];
}
#右侧-------tableView的数据源
[self.foodData addObject:datas];
}
[self.view addSubview:self.leftTableView];
[self.view addSubview:self.rightTableView];
[self.leftTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]
animated:YES
scrollPosition:UITableViewScrollPositionNone];
- 初始化左右两侧的tableView
- (UITableView *)leftTableView {
if (!_leftTableView) {
_leftTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, leftTableViewWidth, leftTableViewHeight)];
_leftTableView.delegate = self;
_leftTableView.dataSource = self;
_leftTableView.rowHeight = 55;
_leftTableView.tableFooterView = [UIView new];
_leftTableView.showsVerticalScrollIndicator = NO;
_leftTableView.separatorColor = [UIColor clearColor];
[_leftTableView registerClass:[LeftTableViewCell class] forCellReuseIdentifier:kLeftCellIdentifier];
}
return _leftTableView;
}
- (UITableView *)rightTableView {
if (!_rightTableView) {
_rightTableView = [[UITableView alloc] initWithFrame:CGRectMake(leftTableViewWidth, 0, SCREEN_WIDTH - leftTableViewWidth, rightTableViewHeight)];
_rightTableView.delegate = self;
_rightTableView.dataSource = self;
_rightTableView.rowHeight = 80;
_rightTableView.showsVerticalScrollIndicator = NO;
[_rightTableView registerClass:[RightTableViewCell class] forCellReuseIdentifier:kRightCellIdentifier];
}
return _rightTableView;
}
- 实现tableView的数据源和代理方法
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (_leftTableView == tableView) {#//左侧只有1组
return 1;
}
else {#//右侧的组数 == 左侧的行数
return self.categoryData.count;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (_leftTableView == tableView) {
return self.categoryData.count;
}
else {
return [self.foodData[section] count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {#//正常逻辑设置cell内容
if (_leftTableView == tableView) {
LeftTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier_Left forIndexPath:indexPath];
FoodModel *model = self.categoryData[indexPath.row];
cell.name.text = model.name;
return cell;
}
else {
RightTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier_Right forIndexPath:indexPath];
FoodModel *model = self.foodData[indexPath.section][indexPath.row];
cell.model = model;
return cell;
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
if (_rightTableView == tableView) {#//右侧tableView显示组头
return 20;
}
return 0;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
if (_rightTableView == tableView) {
TableViewHeaderView *view = [[TableViewHeaderView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 20)];
FoodModel *model = self.categoryData[section];
view.name.text = model.name;
return view;
}
return nil;
}
下面是最重要的联动环节
先左边的 TableView 关联右边的 TableView:点击左边的 TableViewCell,右边的 TableView 跳到相应的分区列表头部
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
if (_leftTableView == tableView) {
[_rightTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:indexPath.row] atScrollPosition:UITableViewScrollPositionTop animated:YES];
[_leftTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:0]
atScrollPosition:UITableViewScrollPositionTop
animated:YES];
}
}
再将右边的 TableView 关联左边的 TableView,这个过程比较繁琐,需要理清逻辑
- 先在UISrcollViewDelegate的滚动代理方法里面判断滚动方向
然后在sectionHeaderView的代理方法里面处理联动效果- 在sectionHeaderView展示结束的代理方法里面,判断RightTableView 滑动的方向向上,而且是用户拖拽而产生滚动的,那么 LeftTableView 的选中行就是 RightTableView 的当前 section + 1。
- 在sectionHeaderView即将展示的代理方法里面,判断RightTableView的滑动方向向下,而且是用户拖拽而产生滚动的,那么 LeftTableView 的选中行就是 RightTableView 的当前 section
清楚这个逻辑之后,下面就好处理了
#pragma mark - UISrcollViewDelegate 第一步判断方向
// 标记一下RightTableView的滚动方向,是向上还是向下
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
static CGFloat lastOffsetY = 0;
UITableView *tableView = (UITableView *) scrollView;
if (_rightTableView == tableView) {
_isScrollUp = lastOffsetY < scrollView.contentOffset.y;
lastOffsetY = scrollView.contentOffset.y;
}
}
#pragma mark - TableView分区标题展示结束 第二步
- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section
{
// 当前的tableView是RightTableView,RightTableView滚动的方向向下,RightTableView是用户拖拽而产生滚动的((主要判断RightTableView用户拖拽而滚动的,还是点击LeftTableView而滚动的)
if ((_rightTableView == tableView)
&& _isScrollUp
&& (_rightTableView.dragging || _rightTableView.decelerating))
{
if (section + 1 < self.categoryData.count) {
[self selectRowAtIndexPath:section + 1];
}
}
}
#pragma mark - TableView分区标题即将展示 第三步
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(nonnull UIView *)view forSection:(NSInteger)section
{
// 当前的tableView是RightTableView,RightTableView滚动的方向向上,RightTableView是用户拖拽而产生滚动的((主要判断RightTableView用户拖拽而滚动的,还是点击LeftTableView而滚动的)
if ((_rightTableView == tableView)
&& ! _isScrollUp
&& (_rightTableView.dragging || _rightTableView.decelerating))
{
[self selectRowAtIndexPath:section];
}
}
// 当拖动右边TableView的时候,处理左边TableView
- (void)selectRowAtIndexPath:(NSInteger)index
{
[_leftTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]
animated:YES
scrollPosition:UITableViewScrollPositionTop];
}
后期再整理 TableView 与 CollectionView 之间的联动
参考
https://www.jianshu.com/p/7e534656988d
https://github.com/leejayID/Linkage
网友评论