美文网首页IOS个人开发demo技术
iOS-tableView联动你就看我

iOS-tableView联动你就看我

作者: 麦穗0615 | 来源:发表于2016-07-28 10:42 被阅读2228次

    让我们共同学习一下tableView联动,我这也是从简书上看来的一篇文章,来亲自实现一下。学习文章地址:http://www.jianshu.com/p/dfb73aa08602

    先上图:

    1212.gif
    功能需求(两点):
    • 点击左边tableVIew的cell,右边的tableView滑动至指定位置。
    • 滑动右边tableView的cell,左边的tableView滑动至指定位置。
    具体思路:
    • 实现点击左边tableView同时滚动右边tableView,只需要实现tableView的代理方法。
      - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
      然后在代理方法里边拿到右边的tableView,实现让其滚动到第indexPath.row分区,第0行即可,代码如下:
      - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
      // 如果点击的是右边的tableView,不做任何处理
      if (tableView == self.rightTableView) return;
      // 点击左边的tableView,设置选中右边的tableView某一行。
      左边的tableView的每一行对应右边tableView的每个组第0行
      [self.rightTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:indexPath.row] animated:YES scrollPosition:UITableViewScrollPositionTop];
      }
      我们这里不处理右边tableView的点击事件,所以
      if (tableView == self.rightTableView) return;
      接下来,拖动右边的tableView,来找到左边tableView对应的某一行。
      我们要动态选中左边的tableView,就需要拿到右边tableView现在滚动到了那个组。UITableView有两个代理方法:
      // 一个头标题即将显示的时候调用
      - (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
      // 一个头标题即将消失的时候掉用
      - (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section
      利用这两个方法就可以拿到当前所在哪个组实现这个功能了。

    还有一个更简单的方法,在tableView中,是不常用的,叫做,indexPathsForVisibleRows官方文档解释是:

    The value of this property is an array of NSIndexPath objects each representing a row index and section index that together identify a visible row in the table view. If no rows are visible, the value is nil.
    大概意思是:返回一个屏幕上可见的cell的indexPath集合

    好的,重点来了,拿到这个集合,不就能拿到目前屏幕上顶端的cell的indexpath了吗,那就如愿以偿的拿到现在所在第indexpath.section个分区了。
    上代码:
    #pragma mark - UIScrollViewDelegate
    -(void)scrollViewDidScroll:(UIScrollView *)scrollView{
    // 监听tableView滑动
    // 如果现在滑动的是左边的tableView,不做任何处理
    if ((UITableView *)scrollView == self.leftTableView) return;
    // 滚动右边tableView,设置选中左边的tableView某一行。
    indexPathsForVisibleRows属性返回屏幕上可见的cell的indexPath数组,
    利用这个属性就可以找到目前所在的分区
    [self.leftTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:self.rightTableView.indexPathsForVisibleRows.firstObject.section inSection:0] animated:YES scrollPosition:UITableViewScrollPositionMiddle];
    }
    [详解]:

    • 首先监听scrollView的拖动,本demo不处理左边tableView的滚动,所以
      if ((UITableView *)scrollView == self.leftTableView) return;
    • 下一句代码的意思是,拿到当前屏幕上可见cell的第一行cell所在的分区,然后让左边的tableView选中第0分区(它只有一个分区)的这一行就OK了。
      self.rightTableView.indexPathsForVisibleRows.firstObject.section
      demo地址:https://github.com/RenZhengYang/ZYLinkageTableView

    --------------------------补充-------------------------------

    1.点击左边tableView的时候会有阴影效果

    • 点击左边的tableView,右边的tableView是从当前位置动画滚动到相应位置的,既然有滚动,就会调
      - (void)scrollViewDidScroll:(UIScrollView *)scrollView
      这个代理方法,说白了就是拖动了右边tableView,拖动右边的过程中会陆续选中左边。

    如果不想要这个效果,有两个办法,一个是直接把
    - (void)tableView:(UITableView )tableView didSelectRowAtIndexPath:(NSIndexPath )indexPath
    中的动画滚动的属性
    animated值改成NO**
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    // 如果点击的是右边的tableView,不做任何处理
    if (tableView == self.rightTableView) return;
    // 点击左边的tableView,设置选中右边的tableView某一行。
    左边的tableView的每一行对应右边tableView的每个分区
    [self.rightTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:indexPath.row] animated:NO scrollPosition:UITableViewScrollPositionTop];
    }
    这样做右边的tableView就是无动画滚动了,也就不会再调scrollViewDidScroll:方法。
    但是如果还想右边tableViewyou滚动效果,另一种解决方法是把
    - (void)scrollViewDidScroll:(UIScrollView *)scrollView
    方法换成
    - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
    这个代理方法方法就行了。有的界面好像就是这样做的,但是有bug(估计饿了么没测出来),这个方法的注释为

    // called when scroll view grinds to a halt 当滚动视图戛然而止--有道翻译如是说

    这个方法调用与否在于你的手指是否在动画停止之前离开了屏幕,如果在动画结束之前手指离开屏幕,此方法调用没什么问题。but,如果动画已经停止,再把手指拿开,这个方法是不会调的。

    解决这个bug的关键在于,让手指离开的时候手动调一次这个代理方法,那怎么才能知道手指什么时候离开呢?scrollView给我们了另一个代理方法:
    - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
    这个方法在结束拖拽的时候调,正好解决了我们的问题:
    - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{
    // 推拽将要结束的时候手动调一下这个方法
    [self scrollViewDidEndDecelerating:scrollView];
    }

    • 学习小记:
      1.// 默认选择左边tableView的第一行
      [_leftTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:YES scrollPosition:UITableViewScrollPositionTop];
      必须在tableView数据加载完毕后,才会调用。否则会报错。

    本篇文章,与学习作者文章相同,只不过排版,被我改了,demo中的写法,被我改了。整理一下,学习备用。若有侵权,请及时联系,我会做更改。如有欠缺,或有好的想法,请即时提出。互相交流学习,欢迎点星,鼓励!!!

    相关文章

      网友评论

      本文标题:iOS-tableView联动你就看我

      本文链接:https://www.haomeiwen.com/subject/cjoojttx.html