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 之間的聯動就這么實現了,是不是也很簡單。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM