#15 模仿 Instagram App (IG), Collection View Header & Cell 製作#2

接續上一篇,
這篇實作Collection View與 Json資料結合

Collection View Cell (照片牆顯示)

Collection view controller 跟 Table view controller 原理相似。

Collection View Controller Class
(New > File > Cocoa Touch Class > UICollectionViewController)
這裡命名為 : InstagramCollectionViewController

Collection View Cell Class
(New > File > Cocoa Touch Class > UICollectionViewCell)
這裡命名為 : InstagramCollectionViewCell

Main.storyboard > Collection View Controller

Instagram Collection View Controller 的 Custom Class,選擇剛建立 InstagramCollectionViewController Class

Collection View Cell 的 Custom Class,選擇剛建立的InstagramCollectionViewCell Class

設定Collection View Cell 的 ID
這裡命名為 : InstagramCollectionViewCell

連結Cell 上的 ImageView Outlet 到 InstagramCollectionViewCell.swift
Main.storyboard >> Collection View Controller >> ImageView
這裡命名為:showImageView

設定showImageView AutoLayout
ImageView 加上寬度 100 和比例 1:1 的條件、ImageView在Cell內的Constraints上下左右的間距為 0。
(寬度100是暫時設定的,下面會透過程式修改)

連結Cell 上的 ImageView Width Constraints Outlet 到 InstagramCollectionViewCell.swift
Main.storyboard >> Collection View Controller >> ImageView >> width constraints
這裡命名為:cellWidthConstraints

設定一排固定照片數量的 cell 大小,cell 的大小必須隨著不同的 iPhone 的尺寸變化。例如:實現一排 3 張正方形的照片,照片間的間距為 3,總共有 2 個間距,寬度 414 的 iPhone 11 時,

cell 的寬度計算=(414 - 3* 2) / 3 = 136

當 storyboard 裡的 cell 產生時,它會先呼叫 function awakeFromNib,因此我們在裡面將 widthConstraint 設成依據 iPhone 螢幕計算的寬度。
(這裡設定一排 3 張照片,間距為 3)

class InstagramCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var showImageView: UIImageView!
@IBOutlet weak var cellWidthConstraints: NSLayoutConstraint!

static let width = floor((UIScreen.main.bounds.width - 3 * 2) / 3)
override func awakeFromNib() {
super.awakeFromNib()
cellWidthConstraints?.constant = Self.width
}
}

Min Spacing 也要設定

InstagramCollectionViewController.swift
將 reuseIdentifier 設為 InstagramCollectionViewCell

private let reuseIdentifier = "InstagramCollectionViewCell"

@objc open func numberOfSections(in collectionView: UICollectionView) -> Int,這是回傳 collectionView 顯示 Section 的數量。

override func numberOfSections(in collectionView: UICollectionView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}

@objc open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
,這是回傳 collectionView 顯示 Item 的數量,此數量大小取決於 Instagram API 回傳的資料量。

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of items
return insagramPicUrl.count
}

@objc open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell,
這是回傳 cell 顯示的內容,先將 cell 轉型成自己建立的 InstagramCollectionViewCell後,再設定cell的內容,這裡做下載 Instagram貼文的圖檔並更新cell的ImageView。

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// Configure the cell

guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as? InstagramCollectionViewCell else { return UICollectionViewCell()}
let item = insagramPicUrl[indexPath.item]
URLSession.shared.dataTask(with: item.node.display_url) { (data, response, error) in
if let data = data{
DispatchQueue.main.async {
cell.showImageView.image = UIImage(data: data)
}
}
}.resume()

return cell
}

Collection View Header (使用者相關資料)

照片牆上方有使用者帳號、名稱 、自我介紹 、總貼文數、粉絲人數、追蹤者數量 、頭像的資料,這部分是屬於 Collection View Header。

TableView可以直接拉一個View來做Header設計,而 CollectionView 要使用 Collection Reusable View 做Header設計,建立的方法與Cell相似。

Collection View Controller Class
(New > File > Cocoa Touch Class > UICollectionReusableView)
這裡命名為 : InstagramCollectionHeaderReusableView

Main.storyboard > Collection Reusable View

Collection Reusable View 的 Custom Class,選擇剛建立 InstagramHeaderCollectionReusableView Class

設定CollectionViewReusableView 的 ID
這裡命名為 : InstagramHeaderCollectionViewReusableView

InstagramCollectionViewController.swift

@objc open func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView

這是回傳 ReusableView 顯示的內容,

CollectionViewReusableView可以選擇要做Header 或 Footer 類型
這裡先設定類型為Header

ofKind: UICollectionView.elementKindSectionHeader

將 withReuseIdentifier 設為 InstagramHeaderCollectionViewReusableView

withReuseIdentifier: "InstagramHeaderCollectionViewReusableView"

reusableView 轉型成自己建立的 InstagramHeaderCollectionViewReusableView後,再設定ReusableView的內容,帳號、名稱 、自我介紹 、總貼文數、粉絲人數、追蹤者數量 、頭像的資料。

override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {guard let reusableView =
collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "InstagramHeaderCollectionViewReusableView", for: indexPath) as? InstagramHeaderCollectionReusableView else {return UICollectionReusableView()}

return reusableView
}

最後Layout弄一弄,就可以顯示模仿的Instagram首頁囉!

--

--