2012-11-01 112 views
36

在研究iOS6新功能時,我得到了一個關於UICollectionView的問題。
我目前正在使用流佈局測試它,並將滾動方向設置爲水平,滾動和分頁啓用。我已經將其大小設置爲與我的自定義單元格完全相同,因此它可以一次顯示一個,並且通過向側面滾動,用戶可以看到其他現有單元格。iOS6 UICollectionView和UIPageControl - 如何獲取可見單元格?

它完美的作品。

現在我想添加和UIPageControl我收集的視圖,因此它可以顯示哪個單元格是可見的,有多少單元格。

構建頁面控件相當簡單,定義了frame和numberOfPages。

問題我正在問題標題標記是如何獲取哪些單元格當前在集合視圖中可見,因此它可以更改頁面控件的currentPage。

我已經嘗試委託方法,如cellForItemAtIndexPath,但它使載入單元格,而不是顯示它們。 didEndDisplayingCell在單元格不再顯示時觸發,與我需要的相反。

它似乎是-visibleCells和-indexPathsForVisibleItems,集合視圖方法,是我的正確選擇,但我遇到了另一個問題。什麼時候觸發它們?

在此先感謝,希望我讓自己清楚明白,以便你們能理解我!

回答

91

必須自己設置爲UIScrollViewDelegate並實現scrollViewDidEndDecelerating:方法,像這樣:

Objective-C的

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 
{ 
    CGFloat pageWidth = self.collectionView.frame.size.width; 
    self.pageControl.currentPage = self.collectionView.contentOffset.x/pageWidth; 
} 

斯威夫特

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { 

    let pageWidth = self.collectionView.frame.size.width 
    pageControl.currentPage = Int(self.collectionView.contentOffset.x/pageWidth) 
} 
+2

無需創建爲一個的CollectionView IVAR: ' - (無效)scrollViewDidEndDecelerating:(UIScrollView中*)滾動視圖 { CGFloat的頁寬= _tutorialCollectionViewFrame.size.width; _pageControl.currentPage = scrollView.contentOffset.x/pageWidth; }' – mmackh

+1

+10,如果我能:d – Omarj

+1

是啊,這是正確的答案...:FUNC scrollViewDidEndDecelerating(滾動視圖:UIScrollView的){ 讓PAGEWIDTH:CGFloat的= self.collectionView.frame.size.width self.pageControl.currentPage = Int(self.collectionView.contentOffset.x/pageWidth) } –

18

我也爲此苦苦掙扎了一段時間,然後建議查看UICollectionView的父類。其中一個碰巧是UIScrollView,如果您將自己設置爲UIScrollViewDelegate,則可以訪問非常有用的方法,例如scrollViewDidEndDecelerating,這是更新UIPageControl的好地方。

+0

非常感謝!解決了我的問題。 – gazzola

+0

我在我的UIViewController中添加了委託,但仍然沒有調用該方法。任何想法? – Dejell

+0

@Dejel記得設置滾動視圖的代表。 – user1898829

16

我會建議一個小調整計算和處理,因爲它會更新以更好的精度立即在任何滾動位置進行頁面控制。

下面的解決方案與任何滾動視圖工作,或者它的子類(UITableView的UICollectionView等)

在viewDidLoad方法

寫這

scrollView.delegate = self 

然後使用代碼你的語言:

斯威夫特3

func scrollViewDidScroll(_ scrollView: UIScrollView) 
    { 
     let pageWidth = scrollView.frame.width 
     pageControl.currentPage = Int((scrollView.contentOffset.x + pageWidth/2)/pageWidth) 
    } 

斯威夫特2:

func scrollViewDidScroll(scrollView: UIScrollView) 
{ 
    let pageWidth = CGRectGetWidth(scrollView.frame) 
    pageControl.currentPage = Int((scrollView.contentOffset.x + pageWidth/2)/pageWidth) 
} 

目標C

- (void)scrollViewDidScroll:(UIScrollView *)scrollView 
{ 
    CGFloat pageWidth = self.collectionView.frame.size.width; 
    self.pageControl.currentPage = (self.collectionView.contentOffset.x + pageWidth/2)/pageWidth; 
} 
+0

您的計算效果更好,但是' - [scrollViewDidEndDecelerating:]'這個代碼更好。 – k06a

+0

這取決於我的想法。 Apple在滾動完成後更新pageControl,但對於我來說,更新頁面控制對用戶來說更爲經常。如果不降低性能,可以使用此方法。 –

+0

在這種情況下,我在點擊「UIPageControl」的左側和右側部分時看到閃爍不好。我的意思是通過'UIPageControl'點擊改變頁面。 – k06a

5
  1. 廣場的PageControl在視圖或代碼集。
  2. 設置UIScrollViewDelegate
  3. 的CollectionView - > cellForItemAtIndexPath(方法)中,加入以下 代碼計算的頁數,

INT頁 =地板(ImageCollectionView.contentSize。寬度/ ImageCollectionView.frame.size.width); [pageControl setNumberOfPages:pages];

添加滾動型代表方法,

編譯馬克 - UIScrollVewDelegate爲UIPageControl

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 
{ 
    CGFloat pageWidth = ImageCollectionView.frame.size.width; 
    float currentPage = ImageCollectionView.contentOffset.x/pageWidth; 

    if (0.0f != fmodf(currentPage, 1.0f)) 
    { 
     pageControl.currentPage = currentPage + 1; 
    } 
    else 
    { 
     pageControl.currentPage = currentPage; 
    } 
    NSLog(@"finishPage: %ld", (long)pageControl.currentPage); 
} 
8

用更少的代碼的另一種選擇是使用可視項指數路徑和設置頁面控制。

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { 
    self.pageControl.currentPage = [[[self.collectionView indexPathsForVisibleItems] firstObject] row]; 
} 
+0

這將是最簡單的,它確實工作 – anoop4real

3

簡單斯威夫特

public func scrollViewDidEndDecelerating(scrollView: UIScrollView) { 
    pageControl.currentPage = (collectionView.indexPathsForVisibleItems().first?.row)! 
} 

UIScrollViewDelegate如果實現UICollectionViewDelegate

+0

我發現接受的答案效果更好,因爲它需要在滾動視圖中間的行。 – markhorrocks

4

已經實現我知道這是一個古老的,但我只需要再次實現這種功能的並有一點補充,這給出了一個更完整的答案。

首先:使用scrollViewDidEndDecelerating假定用戶擡起他們的手指的同時拖動(更像輕彈動作),因此有一個減速階段。如果用戶在沒有擡起手指的情況下拖動,則UIPageControl仍將指示拖動開始之前的舊頁面。相反,使用scrollViewDidScroll回調意味着視圖在拖動和滑動後以及在拖動和滾動期間都會更新,因此對用戶來說感覺更加靈敏和準確。

其次:依靠pagewidth計算所選索引假定所有單元格具有相同的寬度,並且每個屏幕有一個單元格。利用方法UICollectionView提供了更具彈性的結果,這將適用於不同的佈局和單元大小。下面的實現假定幀的中心是要在pagecontrol中表示的所需單元。另外,如果存在小區間距,那麼在selectedIndex可能爲零或可選時,會在滾動期間出現時間,因此需要在設置pageControl之前檢查並解包。

func scrollViewDidScroll(scrollView: UIScrollView) { 
    let contentOffset = scrollView.contentOffset 
    let centrePoint = CGPointMake(
    contentOffset.x + CGRectGetMidX(scrollView.frame), 
    contentOffset.y + CGRectGetMidY(scrollView.frame) 
    ) 
    if let index = self.collectionView.indexPathForItemAtPoint(centrePoint){ 
    self.pageControl.currentPage = index.row 
    } 
} 

一兩件事 - 設置對UIPageControl的頁數像這樣的東西:

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
    self.pageControl.numberOfPages = 20 
    return self.pageControl.numberOfPages 
    } 
相關問題