HorizontalTableView相關的(下面還有對于scrollView的討論)
上次寫了一篇實現橫向pageView的文章,地址在這里,本來是想把上次的pageView補全的,后來想想不如直接寫一個橫向的tableView好了。于是就有了這篇文章。
先上代碼,github地址在這,再看demo 效果
其實橫向的tableView的實現基本和上次的pageView差不多,主要需要的也就是一個復用cell池和可視cell池并及時更新他們。
與pageView相比只是多了一個cellIdentifiy來取對應的cell,另一個就是如何獲取現在可視區域的cell及對應的位置(因為現在每一個cell的寬度不一定了)。
所以比起上次的pageView,我們只要獲取現在要顯示的cells開始index和一共有幾個cell需要展示,在這里我們用一個range來表示他們,然后根據range來判斷要顯示cell的和不顯示的cell并對 visibleListViewsItems 和 dequeueViewPool 做更新,然后計算要顯示的cell的位置,這樣子一個有復用功能的橫向的tableView就搞定了。
而另外一個多出來的需求cellIdentifiy 就需要我們新建一個屬于自己的baseCell來配合,我們該cell帶一個identifiy屬性,在從復用池(dequeueViewPool)獲取cell的時候對identifiy做一次判斷,如果有對應cell的identifiy則取出,沒有則新建即可。
這次我并沒有使用block,主要是上次復用view的返回用block之后發現返回需要的cell那一部分太大段了,還不如分開來寫。而且這樣也更好地模仿了系統的tableView,所以我也設了一個dataSource 和一個actionDelegate(我想用delegate來著),但是。。。delegate已經被scrollView用了。
這里上一下我們的HorizontalTableView的數據源,代理和幾個簡單地方法
//@property (nonatomic, weak) id<ZqwTableViewDelegate> actionDelegate; 最基本的處理點擊事件
- (void) zqwTableView:(ZqwHorizontalTableView*)tableView didTapAtColumn:(NSInteger)column;
//@property (nonatomic, weak) id<ZqwTableViewDataSource> dataSource; 1、 多少個cell 2、 對應的寬度 3、 獲取cell
- (NSInteger)numberOfColumnsInZqwTableView:(ZqwHorizontalTableView *)tableView;
- (ZqwTableViewCell *)zqwTableView:(ZqwHorizontalTableView *)tableView cellAtColumn:(NSInteger)column;
- (CGFloat)zqwTableView:(ZqwHorizontalTableView *)tableView cellWidthAtColumn:(NSInteger)column;
@interface ZqwHorizontalTableView : UIScrollView
- (ZqwTableViewCell *)dequeueZqwTalbeViewCellForIdentifiy:(NSString *)identifiy;
- (void)reloadData;
具體如何使用可以看git上的demo
另外再上一個scrollView相關的
順便附上一個自己實現一部分功能的scrollView
git地址在這里
這個demo主要就是為了演示scrollView的工作原來,為什么scroll能拖動,所謂的contentOffset,和contentSize代表著什么。
-
scrollView 為什么能滾動.我們知道每個視圖都有一個 bounds和 frame。當我們要去布局一個界面時,我們需要處理視圖的 frame。這個屬性允許我們設置視圖的位置和大小。視圖的 frame 和 bounds 的大小總是一樣的,但是他們的 origin 有可能不同。弄懂這兩個屬性的工作原理是理解 UIScrollView 的關鍵。
先放出兩個公式
viewPosition.x = View.frame.origin.x - Superview.bounds.origin.x;
viewPosition.y = View.frame.origin.y - Superview.bounds.origin.y;
現在有一個父視圖和若干個子視圖,一般情況,父視圖的bounds.origin都是(0,0),子視圖的位置則是frame相對于bounds.origin(0,0)的位置,一般子視圖的動畫或者移動,都是對子視圖frame的改變。
現在我們來觀察scrollView,移動scrollView的時候所有的子視圖的位置好像都改變了。如果我們想要改變子視圖的frame來做出這種效果,我們需要同時調整所有子視圖的frame。這樣操作量太大,這時候來看我們之前的公式,想要改變位置,不一定要改變子視圖的frame,而通過改變父視圖的bounds來實現。所以,改變scrollView的bounds就是我們滑動scrollView的本質。
-
contentOffset 是scrollView特有的一個屬性,但其實我們通過上面的分析可以很快的了解到,這個屬性的實質就是bounds.origin。這里貼一下contentOffset的setter 和 getter方法。
- (void)setContentOffset:(CGPoint)offset{ CGRect bounds = [self bounds]; bounds.origin = offset; [self setBounds:bounds]; } - (CGPoint)contentOffset{ return self.bounds.origin; }
contentSize 這個屬性是規定了scrollView可滾動區域的屬性。當contentSize小于bounds.size時則不能滑動,當contentSize大于bounds.size時則可滑動,對應的contentOffset的最大值等于contentSize減去對應的bounds.size。
我寫的scrollView的demo只是簡單實現了scrollView滑動的功能,其他的屬性比如減速,bounces這些增強使用體驗的效果我們可以用facebook的pop來實現,這里就不細聊了。
歡迎討論~