iOS 相似美團外賣 app 兩個 tableView 聯動效果實現

寫在前面git

 

首先聲明哈,不是廣告,我就是用的時候以爲這個功能比較好玩,就想着實現了一下。效果如圖:github

 

 

接下來簡單的說一下思路吧~atom

 

大致思路spa

 

可能咱們看到這種功能的實現的時候,首先想着的是我在這個控制器中左右各放一個tableView,而後進行關聯。我是用了另外一個思路,具體以下:3d

我建了兩個類LGJCategoryVC用來盛放左邊寫着第幾類的tableView和LGJProductsVC用來盛放右邊寫在各類產品的tableView。而後將LGJProductsVC做爲LGJCategoryVC的childViewController,將LGJProductsVC的viewaddSubView到LGJCategoryVC的view上。代理

代碼實現以下:blog

 

- (void)createProductsVC {事件

 

    _productsVC = [[LGJProductsVC alloc] init];產品

    _productsVC.delegate = self;it

    [self addChildViewController:_productsVC];

    [self.view addSubview:_productsVC.view];

}

 

這樣作有什麼好處呢?簡單的說就是將tableView分離,各自使用一個congtroller,這樣作使每一個控制器管理本身的tableView裏面的事件,能夠更好的分離代碼,下降兩個tableView之間的耦合度,同時也避免了把兩個 tableView放在一個controller裏形成一個controller代碼的冗餘,這樣使邏輯更清晰。

 

接下來講一下咱們點擊左邊tableView的cell的時候怎樣使右邊的tableView跟着滑動。我在LGJCategoryVC也就是左邊tableView的這個代理方法中didSelectRowAtIndexPath作了些操做:

 

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

 

    if (_productsVC) {

        [_productsVC scrollToSelectedIndexPath:indexPath];

    }

}

 

其中這個scrollToSelectedIndexPath方法是在_productsVC中聲明的。這個方法就是具體調動右邊tableView滑動的。

 

#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類中聲明瞭一個協議。

 

@protocol ProductsDelegate <NSObject>

 

- (void)willDisplayHeaderView:(NSInteger)section;

- (void)didEndDisplayingHeaderView:(NSInteger)section;

 

@end

 

同時聲明兩個變量,這兩個變量很是有用。

 

@property(nonatomic, assign)BOOL isScrollUp;//是不是向上滾動

@property(nonatomic, assign)CGFloat lastOffsetY;//滾動即將結束時scrollView的偏移量

 

具體做用就在這裏了:

 

#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的這兩個代理方法

 

- (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類中實現代理方法:

 

#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

相關文章
相關標籤/搜索