一個(gè)UICollectionView有好多個(gè)cell,滑動(dòng)一下,誰(shuí)也不知道會(huì)停留在哪個(gè)cell,滑的快一點(diǎn),就會(huì)多滑一段距離,反之則會(huì)滑的比較近,這正是UIScrollview用戶體驗(yàn)好的地方。
如果想要UICollectionView停留到某個(gè)cell的位置,可以用
- (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated;
這個(gè)方法,還能用scrollPosition這個(gè)參數(shù)控制cell具體停留在上下左右中到底哪個(gè)位置。
那么問(wèn)題來(lái)了:如果我只是隨便滑了一下,我也不知道它會(huì)停在位于哪個(gè)indexPath的cell上,但不管它停在哪個(gè)cell上,我都希望這個(gè)cell剛好在屏幕中間,應(yīng)該怎么辦呢?(這個(gè)場(chǎng)景在coverFlow的效果里比較常見(jiàn))
之前知道的做法是:
在scrollViewDidEndDecelerating或其他delegate方法里,通過(guò)當(dāng)前 contentOffset 計(jì)算最近的整數(shù)頁(yè)及其對(duì)應(yīng)的 contentOffset,然后通過(guò)動(dòng)畫移動(dòng)到這個(gè)位置。
但是這個(gè)做法有問(wèn)題,就是動(dòng)畫不連貫,完全沒(méi)有“剛好停到那里”的感覺(jué)。
今天在想有沒(méi)有其他更好的辦法時(shí),突然發(fā)現(xiàn)一個(gè)之前從來(lái)沒(méi)用功的方法:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset NS_AVAILABLE_IOS(5_0);
一看這參數(shù)名,再看看這文檔,真是讓人喜不自禁吶!這不就是讓scrollView“剛好停到某個(gè)位置”的方法嘛!!!(系統(tǒng)5.0就提供了,現(xiàn)在才看到。。。。。。)
targetContentOffset 是個(gè)指針,可以修改這個(gè)參數(shù)的值,讓scrollView最終停止在目標(biāo)位置。
注意:scrollView的pagingEnable屬性必須為NO時(shí)這個(gè)方法才會(huì)被調(diào)用。
例:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
CGPoint orifinalTargetContentOffset = CGPointMake(targetContentOffset->x, targetContentOffset->y);
*targetContentOffset = [self? itemCenterOffsetWithOriginalTargetContentOffset:orifinalTargetContentOffset];//計(jì)算出想要其停止的位置
}
這樣scrollView就會(huì)逐漸減速,最終停止在itemCenterOffsetWithOriginalTargetContentOffset方法算出來(lái)的位置上了,效果杠杠的~
本來(lái)以為這個(gè)方法沒(méi)多少人知道,結(jié)果百度一搜,發(fā)現(xiàn)原來(lái)已經(jīng)有大神寫過(guò)詳細(xì)的文章了(http://tech.glowing.com/cn/practice-in-uiscrollview/),這個(gè)就當(dāng)記錄一下吧
另外發(fā)現(xiàn)一個(gè)直接用NSObject就實(shí)現(xiàn)類似效果的庫(kù):https://github.com/nicklockwood/iCarousel乍看之下沒(méi)看懂。。。等有空再仔細(xì)研究
更新(2015-06-19)
原來(lái)UICollectionViewLayout已經(jīng)提供了兩個(gè)方法可以實(shí)現(xiàn)這個(gè)功能:
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity;
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset NS_AVAILABLE_IOS(7_0);
效果與上面的delegate方法完全一樣,不過(guò)這個(gè)是UICollectionViewLayout的方法,需要在自己的layout子類里重載。
好處是:這樣就不用再在viewController里寫scrollView的delegate方法了,viewController更加簡(jiǎn)潔;跟布局相關(guān)的代碼都轉(zhuǎn)移到了layout的類中