#32 Use UIScrollViewDelegate protocol to control page dot (with Auto Layout)

來,老師音樂請下!自從 6/17 機智醫生生活2 開播後,每個禮拜都很捨不得看,因為看完就要再等一個禮拜啊啊啊!追 on 檔劇的苦申元浩導演你懂嗎???一個禮拜還只有一集我要哭了(ಥ﹏ಥ)

好,扯太遠,今天要記錄的是如何使用 UIScrollViewDelegate protocol 來控制 UIPageControl 的 currentPage ,先看看成品動畫~

Target

  1. 使用 Auto Layout 來排版各個元件
  2. 使用 UIScrollViewDelegate protocol 來控制 UIPageControl 的 currentPage

Process

Step 1: Add UIScrollView and set Auto Layout

先拉一個 scroll view 出來,設定讓 scroll view 與邊界的距離設為 0 ,這邊犯了一個小錯,因為最後我們想要的成品效果是整頁式的滑動,所以這邊應該把 Constrain to margin 的勾勾取消,不過後面還是可以改的~

設定完成後你會發現紅色驚嘆號,錯誤描述如上圖,說明我們沒有設定滑動的範圍,不過先不理會,等等會設定到。

Step 2: Add Image View into Scroll View and set Stack View

再來就是把 Image View 加到 Scroll View 裡面,並且再用一個 Stack View 包起來。

因為我們要的效果是平行滑動,所以在 Stack View 的屬性設定中調整,將 Axis 調整成 Horizontal 。

Step 3: Let Content Layout Guide equal to Stack View

Content Layout Guide 就是捲動範圍,將捲動範圍設成跟 Stack View 的大小一樣。

Step 4: Let Image View’s size equal to Frame Layout Guide

再來就是將 Image View 的大小設定跟螢幕長寬一樣。

Step 5: Cancel margin

再來就是修正剛剛說的錯誤,把 margin 取消後將 Scroll View 的四邊與 Super View 的四邊距離設成 0 ,看起來就完美了~

Step 6: Add more Image View into Stack View

再來把你要的圖片全都加到 Stack View 裡面。

補充個小細節,在 Scroll View 中的屬性欄位找到 Paging Enable,打勾的話就可以以整頁式的滑動,不會停留在兩張圖的中間。

Step 7: Add UIPageControl

加入今天的另外一個主角,UIPageControl。要注意的是, Page Control 也要記得設定 Auto Layout 喔~

Step 8: Assign delegate

在上一篇說到 Delegate assign 的方式,除了在程式中設定外, Story board 也可以做到這件事情,將 Scroll View 按住右鍵拖曳到 View Controller 放開後,點選 delegate 就成功 assign View Controller 成為代理人了。

可以右鍵點選 Scroll View 查看 delegate 的狀態。

Step 9: Follow protocol and coding

指定完代理人後,再來就是讓代理人遵從 protocol ,可以使用上次提到的 Extension 功能,另外,如果你不知道這個 Protocol 可以做什麼,cmd 按著點選,進到 Jump to Definition 就可以看到他可以做些什麼事情了。

可以看後面 Apple 寫給開發者的註解,但在看這些註解前我覺得更重要的是我們想要做什麼功能?我們想要讓在換頁的時候 Page Control 也跟著換,該用什麼方式做到這個效果呢?

有個方式是,去偵測 Scroll View 移動時的 x 座標,當使用者停下來時的 x 座標的數值去除以照片的寬,得到的這個數值四捨五入去取整數就可以得知使用者目前靠近第幾頁了。

舉例來說,一張照片的寬假設是 100,當使用者向左滑動 40 (畫面向右跑 40) 時,x 座標是 40,40 / 100 = 0.4,四捨五入取整數還是 0,表示目前使用者雖然正在往第二頁靠近,但第二頁只有顯示十分之四使用者就放掉了,所以頁面應該還是維持顯示在第一頁。Page Control 根據這個數值,讓 currentPage 還是維持在 0 ,也就是第一頁。

再舉個例,當使用者向左滑動 60 (畫面向右跑 60) 時,x 座標是 60,60 / 100 = 0.6,四捨五入取整數是 1,表示目前使用者正在往第二頁靠近,而且第二頁已經出現十分之六,這時候放開就應該要顯示第二頁。Page Control 根據這個數值,讓 currentPage 變更為 1,也就是第二頁。

所以看來我們要找的功能是使用者在停止滑動時,要執行的 func。

所以, // called when scroll view grinds to a haltfunc scrollViewDidEndDecelerating 的描述看起來是我們要的。

extension ViewController: UIScrollViewDelegate{func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {let page = scrollView.contentOffset.x / scrollView.bounds.widthpageDot.currentPage = Int(page)}}

把上面的想法打成 code 就會像如上,給大家參考~

Free Talk

導演我需要下一集~~~(劇癮發作)

--

--