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

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

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

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

前言

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

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

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

Usage

正文

一、 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 之间的联动就这么实现了,是不是也很简单。

转载于:https://www.cnblogs.com/sunfuyou/p/7461012.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值