两个 TableView 之间的联动, TableView 与 CollectionView 之间的联动

这是一个创建于 359 天前的主题,其中的信息可能已经有所发展或是发生改变。

[联动] :两个 TableView 之间的联动, TableView 与 CollectionView 之间的联动

前言

现在市面上有很多 app 都有联动功能,有的是两个 TableView 之间的联动,比如美团外卖,百度外卖,饿了么等等。有的是 TableView 与 CollectionView 之间的联动,比如礼物说等等。

本文仿造了美团外卖和礼物说,分别实现了两个 TableView 之间和 TablView 与 CollectionView 之间的联动效果,效果图看下面的 gif 图。

先附上 gif 图的 demo 下载链接,[ Code4App ]配合 demo 一起看文章,效果会更佳。

正文

一、 TableView 与 TableView 之间的联动

下面来说下实现两个 TableView 之间联动的主要思路:

先解析数据装入模型,objectWithDictionary:是将字典转化为模型,这个工具是我用 runtime 写的,一行代码解析数据,具体使用方法可以参考我简书上另一篇文章[ Objective-C 中的 Runtime ]

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];
[self.categoryData addObject:model]; NSMutableArray *datas = [NSMutableArray array];
for (FoodModel *f_model in model.spus)
{
[datas addObject:f_model];
}
[self.foodData addObject:datas];
}

定义两个 TableView : LeftTableView 和 RightTableView 。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
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.productData[indexPath.section][indexPath.row];
cell.model = model;
return cell;
}
}

先将左边的 TableView 关联右边的 TableView :点击左边的 TableViewCell ,右边的 TableView 跳到相应的分区列表头部。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(nonnull NSIndexPath *)indexPath
{
if (_leftTableView == tableView)
{
_selectIndex = indexPath.row;
[_rightTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:_selectIndex] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
}

再将右边的 TableView 关联左边的 TableView :标记一下 RightTableView 的滚动方向,然后分别在 TableView 分区标题即将展示和展示结束的代理函数里面处理逻辑。

  • 1.在 TableView 分区标题即将展示里面,判断当前的 tableView 是 RightTableView , RightTableView 滑动的方向向上, RightTableView 是用户拖拽而产生滚动的(主要判断 RightTableView 是用户拖拽的,还是点击 LeftTableView 滚动的),如果三者都成立,那么 LeftTableView 的选中行就是 RightTableView 的当前 section 。
  • 2.在 TableView 分区标题展示结束里面,判断当前的 tableView 是 RightTableView ,滑动的方向向下, RightTableView 是用户拖拽而产生滚动的,如果三者都成立,那么 LeftTableView 的选中行就是 RightTableView 的当前 section-1 。
// 标记一下 RightTableView 的滚动方向,是向上还是向下
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
static CGFloat lastOffsetY = 0; UITableView *tableView = (UITableView *) scrollView;
if (_rightTableView == tableView)
{
_isScrollDown = lastOffsetY < scrollView.contentOffset.y;
lastOffsetY = scrollView.contentOffset.y;
}
} // TableView 分区标题即将展示
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(nonnull UIView *)view forSection:(NSInteger)section
{
// 当前的 tableView 是 RightTableView , RightTableView 滚动的方向向上, RightTableView 是用户拖拽而产生滚动的((主要判断 RightTableView 用户拖拽而滚动的,还是点击 LeftTableView 而滚动的)
if ((_rightTableView == tableView) && !_isScrollDown && _rightTableView.dragging)
{
[self selectRowAtIndexPath:section];
}
} // TableView 分区标题展示结束
- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section
{
// 当前的 tableView 是 RightTableView , RightTableView 滚动的方向向下, RightTableView 是用户拖拽而产生滚动的(主要判断 RightTableView 用户拖拽而滚动的,还是点击 LeftTableView 而滚动的)
if ((_rightTableView == tableView) && _isScrollDown && _rightTableView.dragging)
{
[self selectRowAtIndexPath:section + 1];
}
} // 当拖动右边 TableView 的时候,处理左边 TableView
- (void)selectRowAtIndexPath:(NSInteger)index
{
[_leftTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] animated:YES scrollPosition:UITableViewScrollPositionTop];
}

这样就实现了两个 TableView 之间的联动,是不是很简单。

二、 TableView 与 CollectionView 之间的联动

TableView 与 CollectionView 之间的联动与两个 TableView 之间的联动逻辑类似。

下面说下实现 TableView 与 CollectionView 之间的联动的主要思路:

还是一样,先解析数据装入模型。

NSString *path = [[NSBundle mainBundle] pathForResource:@"liwushuo" ofType:@"json"];
NSData *data = [NSData dataWithContentsOfFile:path];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSArray *categories = dict[@"data"][@"categories"]; for (NSDictionary *dict in categories)
{
CollectionCategoryModel *model =
[CollectionCategoryModel objectWithDictionary:dict];
[self.dataSource addObject:model]; NSMutableArray *datas = [NSMutableArray array];
for (SubCategoryModel *sModel in model.subcategories)
{
[datas addObject:sModel];
}
[self.collectionDatas addObject:datas];
}

定义一个 TableView ,一个 CollectionView 。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
LeftTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier_Left forIndexPath:indexPath];
CollectionCategoryModel *model = self.dataSource[indexPath.row];
cell.name.text = model.name;
return cell;
} - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kCellIdentifier_CollectionView forIndexPath:indexPath];
SubCategoryModel *model = self.collectionDatas[indexPath.section][indexPath.row];
cell.model = model;
return cell;
}

先将 TableView 关联 CollectionView ,点击 TableViewCell ,右边的 CollectionView 跳到相应的分区列表头部。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
_selectIndex = indexPath.row;
[self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:_selectIndex] atScrollPosition:UICollectionViewScrollPositionTop animated:YES];
}

再将 CollectionView 关联 TableView ,标记一下 RightTableView 的滚动方向,然后分别在 CollectionView 分区标题即将展示和展示结束的代理函数里面处理逻辑。

  • 1.在 CollectionView 分区标题即将展示里面,判断 当前 CollectionView 滚动的方向向上, CollectionView 是用户拖拽而产生滚动的(主要是判断 CollectionView 是用户拖拽而滚动的,还是点击 TableView 而滚动的),如果二者都成立,那么 TableView 的选中行就是 CollectionView 的当前 section 。
  • 2.在 CollectionView 分区标题展示结束里面,判断当前 CollectionView 滚动的方向向下, CollectionView 是用户拖拽而产生滚动的,如果二者都成立,那么 TableView 的选中行就是 CollectionView 的当前 section-1 。
// 标记一下 CollectionView 的滚动方向,是向上还是向下
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
static float lastOffsetY = 0; if (self.collectionView == scrollView)
{
_isScrollDown = lastOffsetY < scrollView.contentOffset.y;
lastOffsetY = scrollView.contentOffset.y;
}
} // CollectionView 分区标题即将展示
- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath
{
// 当前 CollectionView 滚动的方向向上, CollectionView 是用户拖拽而产生滚动的(主要是判断 CollectionView 是用户拖拽而滚动的,还是点击 TableView 而滚动的)
if (!_isScrollDown && collectionView.dragging)
{
[self selectRowAtIndexPath:indexPath.section];
}
} // CollectionView 分区标题展示结束
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(nonnull UICollectionReusableView *)view forElementOfKind:(nonnull NSString *)elementKind atIndexPath:(nonnull NSIndexPath *)indexPath
{
// 当前 CollectionView 滚动的方向向下, CollectionView 是用户拖拽而产生滚动的(主要是判断 CollectionView 是用户拖拽而滚动的,还是点击 TableView 而滚动的)
if (_isScrollDown && collectionView.dragging)
{
[self selectRowAtIndexPath:indexPath.section + 1];
}
} // 当拖动 CollectionView 的时候,处理 TableView
- (void)selectRowAtIndexPath:(NSInteger)index
{
[self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] animated:YES scrollPosition:UITableViewScrollPositionMiddle];
}

TableView 与 CollectionView 之间的联动就这么实现了,是不是也很简单。

ios 两个 TableView 之间的联动, TableView 与 CollectionView 之间的联动的更多相关文章

  1. iOS 两个tableview的 瀑布流

    iOS 两个tableview的 瀑布流1. [代码]Objective-C     ////  DocViewController.m//  getrightbutton////  Created ...

  2. iOS资讯详情页实现—WebView和TableView混合使用(转)

    iOS资讯详情页实现—WebView和TableView混合使用 如果要实现一个底部带有相关推荐和评论的资讯详情页,很自然会想到WebView和TableView嵌套使用的方案. 这个方案是WebVi ...

  3. [IOS]包含增删改查移动的tableView展示+plist文件保存+程序意外退出保存Demo

    做一个tableView,包含增删改移动功能,并且修改值的时候,在按home键的时候会自动保存.如果可以的话使者保存自定义的类数组保存到plist中. 实现步骤: 1.创建一个SingleViewAp ...

  4. iOS:自定义导航栏,随着tableView滚动显示和隐藏

    自定义导航栏,随着tableView滚动显示和隐藏 一.介绍 自定义导航栏是APP中很常用的一个功能,通过自定义可以灵活的实现动画隐藏和显示效果.虽然处理系统的导航栏也可以实现,但是这个是有弊端的,因 ...

  5. IOS JPush 集成步骤(极光远程推送解决方案,支持android和iOS两个平台)

    ●  什么是JPush ●  一套远程推送解决方案,支持android和iOS两个平台 ●  它能够快捷地为iOS App增加推送功能,减少集成APNs需要的工作量.开发复杂 度 ●  更多的信息,可 ...

  6. iOS 两种不同的图片无限轮播

    代码地址如下:http://www.demodashi.com/demo/11608.html 前记 其实想写这个关于无限轮播的记录已经很久很久了,只是没什么时间,这只是一个借口,正如:时间就像海绵, ...

  7. 计算地球上两个坐标点(经度,纬度)之间距离sql函数

    go --计算地球上两个坐标点(经度,纬度)之间距离sql函数 --作者:lordbaby --整理:www.aspbc.com CREATE FUNCTION [dbo].[fnGetDistanc ...

  8. iOS开发小技巧--TableView Group样式中控制每个section之间的距离

    一.TableView的Group样式中,默认的每个section都有sectionHeader和sectionFooter,只要调整这两个的大小就可以实现section之前的间距扩大或缩小 二.项目 ...

  9. iOS利用响应链机制点击tableview空白处关闭键盘-可以作为参考

    http://www.jianshu.com/p/9717b792599c   是原文地址 处理关闭键盘的做法一般分为两种:1.放弃第一响应者身份:2.当前视图结束编辑.通常情况下只要我们在合适的时机 ...

随机推荐

  1. Centos6.5使用yum安装mysql——快速上手必备(转)

    第1步.yum安装mysql[root@stonex ~]#  yum -y install mysql-server安装结果:Installed:    mysql-server.x86_64 0: ...

  2. 【JQuery】jQuery中的常用方法小结

    1.层级选择器     后代选择器     "父元素  后代元素" 比如:$("div p") 选取div元素下所有的p元素 子元素选择器   "父元 ...

  3. 数十种TensorFlow实现案例汇集:代码+笔记

    这是使用 TensorFlow 实现流行的机器学习算法的教程汇集.本汇集的目标是让读者可以轻松通过案例深入 TensorFlow. 这些案例适合那些想要清晰简明的 TensorFlow 实现案例的初学 ...

  4. Haproxy TCP数据转发

    在实际项目中需要用到haproxy做TCP转发,下面主要针对haproxy的安装及TCP数据转发配置进行说明 一.安装Haproxy (1)编译安装Haproxy mkdir -p /data01/h ...

  5. ConcurrentHashMap vs Collections.synchronizedMap()不同

    之前项目中,有用到过Collections.synchronizedMap(),后面发现当并发数很多的时候,出现其他请求等待情况,因为synchronizedMap会锁住所有的资源,后面通过查阅资料, ...

  6. 替代crontab,任务计划统一集中管理系统cronsun简介

    一.背景 crontab 是 Linux 系统里面最简单易用的定时任务管理工具,相信绝大多数开发和运维都用到过.在咱们公司,很多业务系统的定时任务都是通过 crontab 来定义的,时间长了后会发现存 ...

  7. 《自己动手写框架2》:用200行的DBF解析器来展示良好架构设计

    因为工作关系.须要工作其中,须要读取DBF文件.找了一些DBF读取开源软件,要么是太过庞大,动不动就上万行.要么是功能有问题,编码,长度,总之是没有找到一个很爽的. 在万般无奈之下,我老人家怒从心头起 ...

  8. C#两个DataTable拷贝问题:该行已经属于另一个表的解决方法

    一.DataTable.Rows.Add(DataRow.ItemArray); 二.DataTable.ImportRow(DataRow) 三.设置DataTable的tablename,然后.R ...

  9. RxJava学习笔记(组合Observables)(转)

    组合Observable 当我们需要处理多个Observable的时候,我们可以通过Rxjava的组合函数来创建我们自己想要的Observable. Merge RxJava的 merge() 方法将 ...

  10. MySQL中NULL与空字符串

    一些刚刚接触MySQL的孩子,经常会错误的认为NULL与空字符串’  ’是相同的.这看似是一件不重要的事情,但是在MySQL中,这两者是完全不同的.NULL是指没有值,而”则表示值是存在的,只不过是个 ...