隨著換頁更新的 page control 小圓點

使用 iOS App 時,我們時常看到貼心顯示目前所在分頁的小圓點,比方以下 IG App 畫面顯示三張可愛的小王子圖片,小圓點暗示著目前看到的照片是第幾張。

小圓點的型別是 UIPageControl,接下來我們將一步步示範如何加入隨著換頁更新的小圓點。

實作水平滑動的分頁畫面

實現水平滑動的分頁有許多做法,可以用 scroll view,collection view,page view controller,SwiftUI 等。接下來我們假設先參考以下連結,以 stack view 搭配 scroll view 實現。

加入 page control,設定 auto layout 條件

記得 page control 不能加在 scroll view 裡,如果加在 scroll view 上,它會隨著滑動一起移動。我們想要 page control 的小圓點固定在畫面上,滑動時只會更新目前所在頁面的小圓點顏色。

設定頁數為 5。(# of Pages)

設定 page control 的 Auto Layout 條件。

連結 page control 的 outlet

page control 的 property currentPage 代表目前在第幾頁,當它為 0 時,表示在第一頁,第一個小圓點會變色。當它為 1 時,表示在第二頁,第二個小圓點會變色,其它以下類推。

我們的目標是從程式判斷目前滑動到第幾頁,然後更新 page control 的 currentPage。所以我們的第一步是連結 page control 的 outlet,之後才能從程式設定它的 currentPage。

@IBOutlet weak var pageControl: UIPageControl!

設定 scroll view 的 delegate 為 view controller

當 scroll view 滑動停在某個分頁時,它將呼叫 delegate 的 function,因此我們將 controller 設為 scroll view 的 delegate,之後再定義 delegate 的 function。

從 scroll view 連線到 view controller 後放開觸控板。

選擇 delegate。

此時 view controller 順利成為 scroll view 的 delegate。

讓 controller 遵從 protocol UIScrollViewDelegate

extension ViewController: UIScrollViewDelegate {

}

定義 protocol UIScrollViewDelegate 的 function scrollViewDidEndDecelerating(_:)

此 function 將在 scroll view 滑動停止時呼叫。

extension ViewController: UIScrollViewDelegate {
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {

}
}

我們在其中寫程式判斷目前在第幾頁,然後更新小圓點。以下程式算出目前所在頁數後,更新 page control 的 currentPage。

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let page = scrollView.contentOffset.x / scrollView.bounds.width
pageControl.currentPage = Int(page)
}

scrollView.bounds.width 是 scroll view 的寬度,也是分頁的寬度。假設分頁的寬度是 100,那麼第一頁的 x 座標將是 0 ~ 100,第二頁是 100 ~ 200。

而 scrollView.contentOffset.x 則是目前滑動的水平距離,比方數字 50 表示向左滑動了 50 的距離。由於我們將 scroll view 設為分頁模式(isPagingEnabled 為 true),當 scroll view 滑動停止時,它一定剛好停在某個分頁。當 function scrollViewDidEndDecelerating(_:) 被呼叫時,scrollView.contentOffset.x 將為分頁寬度的倍數。比方分頁寬度 100,x 可能會是 0,100,200。因此 scrollView.contentOffset.x / scrollView.bounds.width 可算出目前所在的分頁。比方 scrollView.contentOffset.x 為 200 時,200 / 100 是 2,表示在第三頁。(別忘了第一頁的數字是 0)

結果

當我們滑動分頁時,下方的小圓點也乖乖聽話地更新顏色了。

點選或拖曳小圓點時更新頁面

我們可以在小圓點上用點選或拖曳的方式快速移動到某個小圓點(ps: iOS 14 才支援拖曳),不過預設只有小圓點會更新,頁面並不會更新,我們必須另外加入更新頁面的程式。

  • 連結 scroll view 的 outlet。

為了從程式控制 scroll view 移動到某一頁,我們必須先連結它的 outlet。

@IBOutlet weak var scrollView: UIScrollView!
  • 連結 page control 的 action function,綁定 value changed event。

在小圓點上點選或拖曳造成小圓點更新時,將觸發 page control 的 value change event。

@IBAction func changePage(_ sender: UIPageControl) {


}
  • 更新頁面。

依據 page control 的 currentPage 計算 scroll view 要移動到的 offset。

@IBAction func changePage(_ sender: UIPageControl) {
let point = CGPoint(x: scrollView.bounds.width * CGFloat(sender.currentPage), y: 0)
scrollView.setContentOffset(point, animated: true)

}

--

--

彼得潘的 iOS App Neverland
彼得潘的 Swift iOS App 開發問題解答集

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com