天天看點

iOS-tableView關聯你就看我

讓我們共同學習一下tableView關聯,我這也是從簡書上看來的一篇文章,來親自實作一下。學習文章位址:http://www.jianshu.com/p/dfb73aa08602

先上圖:

iOS-tableView關聯你就看我

1212.gif

功能需求(兩點):
  • 點選左邊tableVIew的cell,右邊的tableView滑動至指定位置。
  • 滑動右邊tableView的cell,左邊的tableView滑動至指定位置。
具體思路:
  • 實作點選左邊tableView同時滾動右邊tableView,隻需要實作tableView的代理方法。
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
               
    然後在代理方法裡邊拿到右邊的tableView,實作讓其滾動到第indexPath.row分區,第0行即可,代碼如下:
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    // 如果點選的是右邊的tableView,不做任何處理
     if (tableView == self.rightTableView) return;
    // 點選左邊的tableView,設定選中右邊的tableView某一行。
       左邊的tableView的每一行對應右邊tableView的每個組第行
    [self.rightTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow: inSection:indexPath.row] animated:YES scrollPosition:UITableViewScrollPositionTop];
    }
               
    我們這裡不處理右邊tableView的點選事件,是以
    if (tableView == self.rightTableView) return;
               

    接下來,拖動右邊的tableView,來找到左邊tableView對應的某一行。

    我們要動态選中左邊的tableView,就需要拿到右邊tableView現在滾動到了那個組。UITableView有兩個代理方法:

    // 一個頭标題即将顯示的時候調用
    - (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
    // 一個頭标題即将消失的時候掉用
    - (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section
               

    利用這兩個方法就可以拿到目前所在哪個組實作這個功能了。

    還有一個更簡單的方法,在tableView中,是不常用的,叫做,indexPathsForVisibleRows官方文檔解釋是:

    The value of this property is an array of NSIndexPath objects each representing a row index and section index that together identify a visible row in the table view. If no rows are visible, the value is nil.
    大概意思是:傳回一個螢幕上可見的cell的indexPath集合
               

    好的,重點來了,拿到這個集合,不就能拿到目前螢幕上頂端的cell的indexpath了嗎,那就如願以償的拿到現在所在第indexpath.section個分區了。

    上代碼:

    #pragma mark - UIScrollViewDelegate
     -(void)scrollViewDidScroll:(UIScrollView *)scrollView{ 
     // 監聽tableView滑動
     // 如果現在滑動的是左邊的tableView,不做任何處理
     if ((UITableView *)scrollView == self.leftTableView) return;      
    // 滾動右邊tableView,設定選中左邊的tableView某一行。
       indexPathsForVisibleRows屬性傳回螢幕上可見的cell的indexPath數組,
       利用這個屬性就可以找到目前所在的分區 
     [self.leftTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:self.rightTableView.indexPathsForVisibleRows.firstObject.section inSection:] animated:YES scrollPosition:UITableViewScrollPositionMiddle];
     }
               
    [詳解]:
  • 首先監聽scrollView的拖動,本demo不處理左邊tableView的滾動,是以
    if ((UITableView *)scrollView == self.leftTableView) return;
               
  • 下一句代碼的意思是,拿到目前螢幕上可見cell的第一行cell所在的分區,然後讓左邊的tableView選中第0分區(它隻有一個分區)的這一行就OK了。 demo位址:https://github.com/RenZhengYang/ZYLinkageTableView

--------------------------補充-------------------------------

1.點選左邊tableView的時候會有陰影效果

  • 點選左邊的tableView,右邊的tableView是從目前位置動畫滾動到相應位置的,既然有滾動,就會調
    - (void)scrollViewDidScroll:(UIScrollView *)scrollView
               
    這個代理方法,說白了就是拖動了右邊tableView,拖動右邊的過程中會陸續選中左邊。
如果不想要這個效果,有兩個辦法,一個是直接把
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
           
中的動畫滾動的屬性animated值改成NO
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 
 // 如果點選的是右邊的tableView,不做任何處理
 if (tableView == self.rightTableView) return;
 // 點選左邊的tableView,設定選中右邊的tableView某一行。
     左邊的tableView的每一行對應右邊tableView的每個分區   
   [self.rightTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow: inSection:indexPath.row] animated:NO scrollPosition:UITableViewScrollPositionTop];
    }
           

這樣做右邊的tableView就是無動畫滾動了,也就不會再調scrollViewDidScroll:方法。

但是如果還想右邊tableViewyou滾動效果,另一種解決方法是把

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
           
方法換成
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
           
這個代理方法方法就行了。有的界面好像就是這樣做的,但是有bug(估計餓了麼沒測出來),這個方法的注釋為
// called when scroll view grinds to a halt 當滾動視圖戛然而止--有道翻譯如是說

這個方法調用與否在于你的手指是否在動畫停止之前離開了螢幕,如果在動畫結束之前手指離開螢幕,此方法調用沒什麼問題。but,如果動畫已經停止,再把手指拿開,這個方法是不會調的。

解決這個bug的關鍵在于,讓手指離開的時候手動調一次這個代理方法,那怎麼才能知道手指什麼時候離開呢?scrollView給我們了另一個代理方法:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
           
這個方法在結束拖拽的時候調,正好解決了我們的問題:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{ 
 // 推拽将要結束的時候手動調一下這個方法
[self scrollViewDidEndDecelerating:scrollView];
 }
           
  • 學習小記:
    // 預設選擇左邊tableView的第一行
    [_leftTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow: inSection:] animated:YES scrollPosition:UITableViewScrollPositionTop];
    必須在tableView資料加載完畢後,才會調用。否則會報錯。
               
    本篇文章,與學習作者文章相同,隻不過排版,被我改了,demo中的寫法,被我改了。整理一下,學習備用。若有侵權,請及時聯系,我會做更改。如有欠缺,或有好的想法,請即時提出。互相交流學習。