本篇文章將按步驟詳細說明,如何在 iOS TableView 中實作 Parallax 的其中一個視覺效果,Demo Project 使用 XCode 8、Swift 3,適合讀者為:
- 了解 ScrollView 的 ContentOffset Property 以及 Delegate Design Patten。
- 熟悉 ImageView 的 ContentMode Property。
- 對 AutoLayout 有基本了解。
下圖為想要實現的效果,上方的 ImageView 會跟著下拉的動作產生相對應的變化。
Step 1 : Download Start Project From Dropbox. (按此下載)
下載後,打開 ParallaxDemo.xcodeproj,裡面已經有一個寫好的 TableView,在每一個 Cell 裡面顯示每一個各自的 Row Number。
Step 2 : 透過 TableView 的 ContentInset property,把 TableView 往下位移,騰出上方的空間,給後續要置入的 ImageView 使用。
在 DemoTableViewController 裡新增一個 imageViewLength property :
class DemoTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {//1
let imageViewHeight: CGFloat = 200.0
...}
在 DemoTableViewController 裡面的 setUpTableView() function 加入下列程式碼:
func setUpTableView() {//2
tableView.contentInset = UIEdgeInsets(top: imageViewHeight, left: 0, bottom: 0, right: 0)//3
tableView.contentOffset = CGPoint(x: 0, y: -imageViewHeight)
...
}
以下說明每一段程式碼的作用:
- 設定要留給 ImageView 的高度,將之存在 ImageViewHeight property 中,以供後續使用。
- 設定 TableView 的 ContentInset,這個屬性的資料型態是 UIEdgeInsets,透過分別設定 top, left, bottom, right,可以調整 TableView 的 Content view 與底下 ScrollView 的相對距離。這裡我們把 ImageViewHeight 作為UIEdgeInset initializer 的 top 參數,並將這個新生成的 UIEdgeInset 物件指定給 TableView 的 ContentInset Property。
- 設定好 ContentInset 後,為了讓一進來 App 的時候,顯示上方的空白,我們還必須設定 TableView 的 ContentOffset,讓上方的空白可以被看見。
設定完這些指令之後,跑模擬器就可以看到下方的畫面:
Step 3 : 新增 ImageView
在 DemoTableViewController 裡新增 setUpImageView function :
並修改 setUp() function:
func setUp() { ... //Add Statement setUpImageView()
}
說明:setUpImageView() 裡面做的事情就是指定 ImageView 所放的 Image,並設定 AutoLayout Constraint。其中重要的是要將 ContentMode 設定成 ScaleAspectFill,這會讓系統自動調整圖片大小,直到圖片的長短邊都充滿整個 ImageView 為止,如果沒有設定這個步驟,Parallax 的效果有可能會失敗,這部分要特別小心。而 ClipToBounds 就是將超出 ImageView 的部分隱藏起來,這樣就不會遮住畫面上的其它元件。
新增完 setUpImageView function 後,跑模擬器就可以看到下方的畫面:
接下來就進到更重要的部分,UIScrollView 有相對應的 Protocol: UIScrollViewProtocol,會在發生一些事件的時候通知委派物件,執行相對應的 method,而 UITableViewDelegate Protocol 繼承自 UIScrollViewDelegate,自然也繼承了這些 method。我們將會用到 scrollViewDidScroll() 這個 function。
將下列的程式碼新增到 DemoTableViewController 中:
以下分別解釋三個 Function :
- scrollViewDidScroll
這個 method 是在每次 ScrollView 觸發 scroll 事件,都會被執行的 delegate method,在這個 method 裡面,我們去讀取現在 ScrollView,也就是 tableView 被滑到了哪裡,並執行相對應的動作。
2. changeImageViewTopConstraint(contentOffset: CGPoint)
當 TableView 被往上滑,row 0, row 1 被滑出畫面,row 10, row 11 以及更下方的 row 進入畫面,此時 ContentOffset 是逐漸變大的,那在 TableView 上方的 ImageView 也要搭配一起消失在畫面中,所以在這個 method 裡面,我們去修改 imageViewTopConstraint,讓它隨著 ContentOffset 的變大而逐漸往畫面上方移動,直到整個移出畫面後就不再修改它,在這過程中我們必須確保 imageViewHeightConstraint 不改變,image 的顯示才不會跑掉。
3. changeImageViewHeightConstraint(contentOffset: CGPoint)
當 TableView 已經被滑到最上層的畫面,還繼續被下拉的時候,我們希望 imageView 變大,來填補空白,所以我們去修改的 imageViewHeightConstraint,讓 imageView 隨著下拉的動作高度變大,而因為 contentMode 設定為 ScaleAspectFill 的關係, imageView 顯示的內容就會有所改變,達到我們想要的效果。
進行到這邊就完成了 Parallax 的效果,最後附上 Final Project 的 Github 連結,如果本文有任何錯誤或是未詳盡的地方,還請不吝到 Github 發 issue 給我,感謝你/妳。
【AppWorks School 新班 — Android Class #1 與 iOS Class #6 限時招生中】遠距 4 週、駐點集訓 16 週,全程免費,幫助你成為新時代的軟體工程師。
Android Class #1 >> https://goo.gl/Efi23t
iOS Class #6 >> https://goo.gl/Xz27kK
歡迎申請加入,來讓我們幫助你加速學習!(申請只到 01/07/2018)