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