最近项目中需要做一个两个tableVIew联动的效果,有点类似于饿了吗外卖点餐的那种效果,虽然实现起来难度不是太大,但是还是记录下来,方便有需要的开发者少走一些弯路.个人认为做什么效果主要还是一个思路问题,思路对了,做起来也就得心应手了.废话不多说,先附上效果图.
示例.gif
具体实现步骤
1 . 首先确定好思路,底层是用viewController, 上面的地址和派送次数的视图是用两个View做的,下面两个tableView ,左边是leftTableView , 右边是rightTableView.这样做的目的是为了tableView滑动到顶部的时候整个视图有个上移的动画效果,这样做更加方便一点.
图1.png
默认选中第一个单元格
[self.leftTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:YES scrollPosition:UITableViewScrollPositionNone];
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath {
if (_leftTableView == tableView) {
AYLeftPickTableViewCell *leftCell = [tableView cellForRowAtIndexPath:indexPath];
leftCell.contentView.backgroundColor = KLightYellowColor;
NSArray *array = [tableView visibleCells];
for (AYLeftPickTableViewCell *leftCell in array) {
leftCell.titleLabel.textColor = [UIColor blackColor];
}
leftCell.titleLabel.textColor = kOrangeTextColor;
[_rightTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:indexPath.row] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[self viewUpAnimationWihtScrollView:scrollView];
if (scrollView == self.rightTableView) {
CGFloat height = scrollView.frame.size.height;
CGFloat contentOffsetY = scrollView.contentOffset.y;
CGFloat bottomOffset = scrollView.contentSize.height - contentOffsetY;
if (bottomOffset <= height) {
NSIndexPath *bottomIndexPath = [[self.rightTableView indexPathsForVisibleRows] lastObject];
NSIndexPath *moveIndexPath = [NSIndexPath indexPathForRow:bottomIndexPath.section inSection:0];
[self.leftTableView selectRowAtIndexPath:moveIndexPath animated:NO scrollPosition:UITableViewScrollPositionMiddle];
} else {
NSIndexPath *topIndexPath = [[self.rightTableView indexPathsForVisibleRows]firstObject];
NSIndexPath *moveIndexPath = [NSIndexPath indexPathForRow:topIndexPath.section inSection:0];
[self.leftTableView selectRowAtIndexPath:moveIndexPath animated:NO scrollPosition:UITableViewScrollPositionMiddle];
}
}else{
return;
}
}
5.当滑动tableView的时候添加动画,tableView向上滑动的时候让View向上偏移.这一步在scrollViewDidScroll:(UIScrollView *)scrollView中调用.
- (void)viewUpAnimationWihtScrollView:(UIScrollView *)scrollView {
if (scrollView.contentOffset.y > 0) {
[self.addressView mas_updateConstraints:^(MASConstraintMaker *make) {
make.left.right.mas_equalTo(0);
make.top.mas_equalTo(-Address_Height+64);
make.height.mas_equalTo(Address_Height);
}];
[UIView animateWithDuration:0.2 animations:^{
[self.view layoutIfNeeded];
self.rightTableView.frame = CGRectMake(LeftTable_Width, SendView_Height+64, kScreenWidth - LeftTable_Width, kScreenHeight - 64 - 50 - SendView_Height);
self.leftTableView.frame = CGRectMake(0, SendView_Height+64, LeftTable_Width, kScreenHeight - 64 - 50 - SendView_Height);
} completion:^(BOOL finished) {
nil;
}];
} else {
[self.addressView mas_updateConstraints:^(MASConstraintMaker *make) {
make.left.right.mas_equalTo(0);
make.top.mas_equalTo(64);
make.height.mas_equalTo(Address_Height);
}];
[UIView animateWithDuration:0.2 animations:^{
[self.view layoutIfNeeded];
self.rightTableView.frame = CGRectMake(LeftTable_Width, Address_Height + SendView_Height+64, kScreenWidth - LeftTable_Width, kScreenHeight - 64 - 50 - Address_Height - SendView_Height);
self.leftTableView.frame = CGRectMake(0, Address_Height + SendView_Height+64, LeftTable_Width, kScreenHeight - 64 - 50 - Address_Height - SendView_Height);
} completion:^(BOOL finished) {
nil;
}];
}
}
这样就实现了两个tableView联动的效果,其中有2个方法比较关键:
-1 .点击leftTableView的时候让rightTableView滚动到指定分区.
[_rightTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:indexPath.row] atScrollPosition:UITableViewScrollPositionTop animated:YES];
-2 .rightTableView滚动的时候,获取当前页面可见的分区行数,
NSIndexPath *topIndexPath = [[self.rightTableView indexPathsForVisibleRows]firstObject];
优化处理
--- 根据卖香蕉的大叔的建议,对tableView单选处理进行优化.以前我写的那种方式是用NSArray *array = [tableView visibleCells];方法遍历出所有的单元格,然后重新改变title的颜色和cell的背景颜色,然后给当前点击的这个单元格重新改变新的颜色,这样的操作不利于tableView的优化,如果cell足够多的时候,这样做会造成界面卡顿.
@property(nonatomic, strong) NSIndexPath *lastPath;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (_leftTableView == tableView) {
NSInteger newRow = [indexPath row];
NSInteger oldRow = (self .lastPath !=nil)?[self .lastPath row]:-1;
if (newRow != oldRow) {
AYLeftPickTableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
newCell.contentView.backgroundColor = KLightYellowColor;
newCell.titleLabel.textColor = kOrangeTextColor;
AYLeftPickTableViewCell *oldCell = [tableView cellForRowAtIndexPath:self.lastPath];
oldCell.contentView.backgroundColor = [UIColor clearColor];
oldCell.titleLabel.textColor = [UIColor blackColor];
}
self.lastPath = indexPath;
[_rightTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:indexPath.row] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
}
AYLeftPickTableViewCell *leftCell = [tableView dequeueReusableCellWithIdentifier:@"AYLeftPickTableViewCell" forIndexPath:indexPath];
AYCollectFoodModel *model = self.dataArray[indexPath.row];
leftCell.titleLabel.text = model.vegname;
leftCell.selectionStyle = UITableViewCellSelectionStyleNone;
NSInteger row = [indexPath row];
NSInteger oldRow = [_lastPath row];
if (row == oldRow && _lastPath!=nil) {
leftCell.contentView.backgroundColor = KLightYellowColor;
leftCell.titleLabel.textColor = kOrangeTextColor;
}else{
leftCell.contentView.backgroundColor = [UIColor clearColor];
leftCell.titleLabel.textColor = [UIColor blackColor];
}
这种处理适用于自定义单元格的单选处理,在这里也正好记录下来,方便给需要用到此功能的开发者多一些思路,再次感谢卖香蕉的大叔给出的意见.
--- 感谢TryToFlyHigher提出的bug,这个bug是由于点击左侧leftTableView让右侧rightTableView滚动的时候,导致左侧的leftTableView又重新选中了一次,就像选中框闪了一下的感觉.目前这个bug已经解决,主要思路是定义一个BOOL值表示是否重复滚动,在左侧leftTableView选中的时候把BOOL值置为YES,在scrollView即将拖动的时候置为NO,在- (void)scrollViewDidScroll:(UIScrollView *)scrollView方法中加上判断,是否重复滚动.
1.定义BOOL值表示是否重复滚动,并给默认值为NO
@property (nonatomic, assign) BOOL isRepeatRolling;
self.isRepeatRolling = NO;
if (self.isRepeatRolling == NO) {
[self.leftTableView selectRowAtIndexPath:moveIndexPath animated:NO scrollPosition:UITableViewScrollPositionMiddle];
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
self.isRepeatRolling = NO;
}
趁着这次打开项目解决掉这个bug,顺便适配了一下iOS11.
gitHub已经更新,再次感谢TryToFlyHigher提出的bug.
结尾
在项目中使用了MJExtension字典转模型,和masonry屏幕适配.
至此就大概实现了列表联动的效果,可以实现的方法有很多,在这里只是提出一个思路,让开发者能够少走一些弯路.
另附本文gitHub地址 ,喜欢的给个星星哦.非常感谢.
作者:PencilCarefully
链接:https://www.jianshu.com/p/c400669e2c1c
相关推荐: