最近大半個月的時間一直忙于編寫一個不大但是也不算簡單的小項目, 更新博客的頻率低了好多. 今天發現并解決了一個問題, 由于查找解決問題的途中發現很少人遇到這個問題, 覺得拿出來說說, 說不定會給以后遇到的人帶來一些便利.
1.頁面上半部分是可以橫向分頁滾動的視圖A, 每頁顯示一個圖表2.隨著視圖A滾動到不同的頁數, 下半部分(視圖B)變換不同的數據3.視圖A每頁的圖表有多處可以點擊,并且點擊事件也會觸發視圖B數據顯示的變換.用圖來表示一下:
頁面要求1.頂部使用UICollectionView作為滾動視圖, 使其cell大小等于自身大小, 每個cell展示一個圖表2.每次滾動完畢及點擊cell中圖表的點時, 獲取collectionView當前展示的cell的indexPath,以此獲取該坐標對應的值展示到下方.
所以,這個功能的關鍵點就在于如何獲取頂部CollectionView當前顯示的cell的indexPath.
我先后試過以下幾種方案:
通過之前做過的自動輪播的廣告banner的經驗(和這個需求有相似的地方),我先采用了之前的方法:通過UICollectionView的-collectionView:didEndDisplayingCell:forItemAtIndexPath:方法得到indexPath更新的時刻, 然后用[collectionViewindexPathsForVisibleItem獲取一組當前顯示的cell們的indexPath的數組,由于我的cell大小剛好等于collectionView的大小,所以這個數組只包含一個元素(后來證明了即使是這樣,這個數組也不一定只有一個元素),我只要取里面的第一個就好了.
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { // 獲取當前顯示的cell的下標 NSIndexPath *firstIndexPath = [[self.collectionView indexPathsForVisibleItems] firstObject]; // 賦值給記錄當前坐標的變量 self.currentIndexPath = indexPathNow; // 更新底部的數據 // ...} 這個方案對于此頁面本身基本可以達到要求,但是由于下級頁面可能會修改到這個頁面的元素,導致cell個數增加或者減小, 有些情況下回到此頁面時會造成程序崩潰.打個比方: 我的collectionView的cell共有3個,并且將cell滑動到最后一頁(最后一個cell),此時記錄當前的下標為2. 下級頁面刪除了一個元素,再回到此頁面的時候,didEndDisplay...方法會最先被調用,這個方法里面會取數據重新設置下半部分視圖的顯示, 而此時當前的下標仍為2, 數據只剩兩個了,就導致了應用的崩潰.
如果從子頁面回來didEndDisplay...方法不被調用或者比較后面被調用,就不會出現這種情況,但是這個方法的調用時機豈是我等可以控制的? 于是乎換了一個方案.
方案二:
通過UIScrollView的
-scrollViewDidEndDecelera方法得到indexPath更新的時刻, 然后用ting: [collectionViewindexPathsForVisibleItem獲取一組當前顯示的cell們的indexPath的數組,和上面的方案一樣,我只要取里面的第一個.s] didEndDecelerating是在scrollView(collectionView)減速完成(滾動停止)的時刻調用的,由于又是pageEnabled == YES, 這個時刻只有一個cell在屏幕上.而且didEndDecelerating不會在從子頁面返回的時候調用,也就解決了方案一的問題.
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { // 獲取當前顯示的cell的下標 NSIndexPath *firstIndexPath = [[self.collectionView indexPathsForVisibleItem s] firstObject]; // 賦值給記錄當前坐標的變量 self.currentIndexPath = indexPathNow; // 更新底部的數據 // ...} 我曾以為問題就這樣解決了,結果意外地發現, 有些時候我點擊cell中圖表的某個點時,cell會跳變為隔壁的cell,查了良久,才發現就是由于對collectionView當前的坐標獲取不準確導致的, 進一步地發現,這個不準確就是由于:即使我的cell大小等于collectionView的大小,在
[collectionViewindexPathsForVisibleItem方法得到的數組數據也有可能大于一個.并且順序還不一定,導致我也不能通過firstObject或者lastObject來獲取我想要的值(我也不知道為什么會大于一個還有不確定的順序).s] 方案三:
再后來,我找到了這個方法:
indexPathForItemAtPoint:---根據某一點得到位于這點上的cell的坐標,而且返回值是一個確定的indexPath,而不是數組,正合我意.需要注意的是,這個方法傳入的參數point是以scrollView的contentView為坐標系的坐標,使用之前要先進行一次轉換.最終我的做法是這樣:- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { // 將collectionView在控制器view的中心點轉化成collectionView上的坐標 CGPoint pInView = [self.view convertPoint:self.collectionView.center toView:self.collectionView]; // 獲取這一點的indexPath NSIndexPath *indexPathNow = [self.collectionView indexPathForItemAtPoint:pInView]; // 賦值給記錄當前坐標的變量 self.currentIndexPath = indexPathNow; // 更新底部的數據 // ...}
新聞熱點
疑難解答