寫在前面
首先宣告哈,不是廣告,我就是用的時候覺得這個功能比較好玩,就想著實現了一下。效果如圖:
接下來簡單的說一下思路吧~
大體思路
可能我們看到這種功能的實現的時候,首先想著的是我在這個控制器中左右各放一個tableView
,然後進行關聯。我是用了另一個思路,具體如下:
我建了兩個類LGJCategoryVC
用來盛放左邊寫著第幾類的tableView和LGJProductsVC
用來盛放右邊寫在各種產品的tableView
。然後將LGJProductsVC
作為LGJCategoryVC
的childViewController,將LGJProductsVC
的view
addSubView到LGJCategoryVC
的view
上。
程式碼實現如下:
1 2 3 4 5 6 7 |
- (void)createProductsVC { _productsVC = [[LGJProductsVC alloc] init]; _productsVC.delegate = self; [self addChildViewController:_productsVC]; [self.view addSubview:_productsVC.view]; } |
這樣做有什麼好處呢?簡單的說就是將tableView
分離,各自使用一個congtroller
,這樣做使每個控制器管理自己的tableView
裡面的事件,可以更好的分離程式碼,降低兩個tableView
之間的耦合度,同時也避免了把兩個 tableView
放在一個controller
裡造成一個controller
程式碼的冗餘,這樣使邏輯更清晰。
接下來說一下我們點選左邊tableView
的cell
的時候怎樣使右邊的tableView
跟著滑動。我在LGJCategoryVC
也就是左邊tableView
的這個代理方法中didSelectRowAtIndexPath
做了些操作:
1 2 3 4 5 6 |
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { if (_productsVC) { [_productsVC scrollToSelectedIndexPath:indexPath]; } } |
其中這個scrollToSelectedIndexPath
方法是在_productsVC
中宣告的。這個方法就是具體調動右邊tableView
滑動的。
1 2 3 4 5 |
#pragma mark - 一級tableView滾動時 實現當前類tableView的聯動 - (void)scrollToSelectedIndexPath:(NSIndexPath *)indexPath { [self.productsTableView selectRowAtIndexPath:([NSIndexPath indexPathForRow:0 inSection:indexPath.row]) animated:YES scrollPosition:UITableViewScrollPositionTop]; } |
我們需要的只是讓右邊tableView
的sectionHeaderView
跟隨左邊的點選cell
移動到最上部就可以了,所以在這裡我們設定selectRowAtIndexPath:([NSIndexPath indexPathForRow:0 inSection:indexPath.row])
接下來就是當我們滑動右邊tableView
的時候左邊的tableView
的cell
跟隨滑動。這裡我們在LGJProductsVC
類中宣告瞭一個協議。
1 2 3 4 5 6 |
@protocol ProductsDelegate <NSObject> - (void)willDisplayHeaderView:(NSInteger)section; - (void)didEndDisplayingHeaderView:(NSInteger)section; @end |
同時宣告兩個變數,這兩個變數非常有用。
1 2 |
@property(nonatomic, assign)BOOL isScrollUp;//是否是向上滾動 @property(nonatomic, assign)CGFloat lastOffsetY;//滾動即將結束時scrollView的偏移量 |
具體作用就在這裡了:
1 2 3 4 5 6 7 8 |
#pragma mark - scrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView { NSLog(@"_lastOffsetY : %f,scrollView.contentOffset.y : %f", _lastOffsetY, scrollView.contentOffset.y); _isScrollUp = _lastOffsetY < scrollView.contentOffset.y; _lastOffsetY = scrollView.contentOffset.y; NSLog(@"______lastOffsetY: %f", _lastOffsetY); } |
在這個方法中,_isScrollUp
用來判斷右邊的tableView
是否是向上滑,當scrollView
滑動時,我們用上次的偏移量和本次的偏移量作對比,如果上次的偏移量小於本次的偏移量說明tableView
是向上滑動的。(關於contentOffset我在上篇的《iOS 實現NavigationController的titleView動態縮放效果》連結:http://www.jianshu.com/p/bcf3d692f99d 中有簡單介紹)此時,_isScrollUp
為YES,反之為NO。我們根據_isScrollUp
這個重要的標識來到這兒:UITableViewDelegate
的這兩個代理方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section { if (self.delegate != nil && [self.delegate respondsToSelector:@selector(willDisplayHeaderView:)] != _isScrollUp) { [self.delegate willDisplayHeaderView:section]; } } - (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section { if (self.delegate != nil && [self.delegate respondsToSelector:@selector(didEndDisplayingHeaderView:)] && _isScrollUp) { [self.delegate didEndDisplayingHeaderView:section]; } } |
在UITableViewDelegate
的這兩個代理方法中,第一個方法是當headerView
將要顯示時呼叫。第二個方法是當headerView
結束顯示時呼叫。在這裡我們根據_isScrollUp
的BOOL值,當headerView
將要顯示的時候說明此時_isScrollUp
為NO,因為此時是向下滑動的。當headerView
結束顯示的時候說明此時_isScrollUp
為YES,因為此時是向上滑動的。此時我們呼叫ProductsDelegate
代理方法,在LGJCategoryVC
類中實現代理方法:
1 2 3 4 5 6 7 8 9 10 |
#pragma mark - ProductsDelegate - (void)willDisplayHeaderView:(NSInteger)section { [self.categoryTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:section inSection:0] animated:YES scrollPosition:UITableViewScrollPositionMiddle]; } - (void)didEndDisplayingHeaderView:(NSInteger)section { [self.categoryTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:section + 1 inSection:0] animated:YES scrollPosition:UITableViewScrollPositionMiddle]; } |
在willDisplayHeaderView
這個代理方法中,右邊tableView
向下滑動,此時headerView
即將顯示,左邊cell
選擇indexPathForRow:section
,在didEndDisplayingHeaderView
代理方法中,右邊tableView
向上滑動,此時headerView
結束顯示,左邊cell
選擇indexPathForRow:section+1
總結
基本的大體思路就是上面這些,可能老是左邊tableView
右邊tableView
的看起來有點兒繞了,具體的還是看程式碼吧。最後貼上程式碼連結:
https://github.com/iOSJason/TableViewTwoLevelLinkageDemo.git
希望可以和大家一起交流,一同進步。3Q
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!
任選一種支付方式