Photo by Erik Lucatero on Unsplash

Peter’s 100 task #5 模仿IG使用者頁面

使用collection view & Interface Builder製作

Tommy
7 min readDec 17, 2020

--

此作業主要實現

  1. 使用flow layout 的collection view製作照片牆
  2. 搭配 Lorem Picsum API抓圖
  3. 滑動後 profile tab 卡在上方的效果
  4. 點選照片後跳到下一頁呈現大圖

這次UI layout的部分使用Sketch&Zeplin製作,這邊分享一個可以免費下載他人設計的Sketch網站(感謝Peter提供)

使用flow layout 的collection view製作照片牆

以下說明一下比較重要的部分,詳細步驟可參考Peter的文章

CollectionView原已遵從UICollectionViewDataSource Protocol,且設定為collection view的datasource.

建立自訂CollectionViewController與CollectionViewCell類別

cell內容的顯示

需注意將cell轉型為自訂的cell類別UserPhotoGridCollectionViewCell

利用URLSession在background thread抓圖片,保持main thread與UI的運作

// 這段程式碼將於background thread執行
{ (data, response, error) in
if let data = data, let image = UIImage(data: data) {
DispatchQueue.main.async {
cell.photoImageView.image = image
}
}
}

更新UI畫面必須利用func DispatchQueue.main.async將程式碼排入main queue執行

設定cell的大小與間距

floor() 回傳不大於參數之最大整數值

Lorem Picsum API抓圖

使用API(https://picsum.photos/seed/picsum(id)/500),抓取指定id照片

滑動後 profile tab 卡在上方的效果

設定collection view上方的空白為379

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 379, left: 0, bottom: 0, right: 0)
}

在Interface Builder放進一個空白的View,高度設為379

畫面設計好後將View拉一個IBOutlet至自訂CollectionViewController類別

@IBOutlet var profileView: UIView!

在viewDidLoad()呼叫自訂addProfileView()加入View

利用frameLayoutGuide與contentLayoutGuide讓profile tab固定在上方

將ProfileView的top設定與contentLayoutGuide的top相同,bottom設定為safeArea的top+50,由於當畫面向上滑動到ProfileView bottom = safeArea top+50時,將產生約束條件的衝突,因此需將profileView的top與contentLayoutGuide的top對齊的priority設定為999,表示若約束條件發生衝突,將先捨去此條件.

點選照片後跳到下一頁呈現大圖

利用IBSegueAction傳送資料

@IBSegueAction func showPhoto(_ coder: NSCoder) -> ShowPhotoViewController? {
let index = self.collectionView.indexPathsForSelectedItems?.first?.item
return ShowPhotoViewController(coder: coder, indexPathItem: index!)
}

用indexPathsForSelectedItems.first.item取得所選擇的item

indexPathsForselectedItems回傳選取cell的陣列,內容為[[section,item]],因此用first取得第一個陣列後,再取得item

--

--