#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首頁囉!
下一篇 :
Reference :