照片牆練習
使用 collection view controller建立
我簡略地列出幾個步驟來建立照片牆
加入新的畫面以及所需要的Controller
首先將原本的畫面刪除(以及與他連結的ViewController),使用 Library在空白的畫面添加兩種 controller:CollectionViewController以及 ViewController ,之後再加上後新增三個檔案
View Controller:用來顯示大張照片,命名為 SelectedPhotoViewController
Collection View Controller:繼承了 UICollectionViewController,用來操控照片牆各項功能,命名為 PhotoCollectionViewController
Collection View Cell:自訂的 cell,在 cell中放入 imageView並且設定 auto layout讓他與cell一樣大,命名為 PhotoCollectionViewCell
加完三個檔案後,先來把畫面建立出來。因為需要能夠讓照片顯示,因此在 Collection View Controller的 collection view cell中增加 imageView,並將auto layout設定成與 cell大小一致,之後 ViewController需要顯示一張大圖,所以也要加上 imageView,如下圖
建立出來後將兩個 Controller與檔案連結起來,連結方法就是在 Class欄位寫出想要連結的檔案,成功連結後會向左邊的 Collection View Controller一樣上方會出現連結的檔案名字,如下圖所示
由於 cell是自訂的,所以也要將cell連結自己定義的檔案
最後因為要在選擇完 cell後就會跳出放大的圖,因此要從 collection view controller的cell拉出一條線連到 view controller
拉完的結果長這樣
遵守 UICollectionViewDataSource protocol
在建立 CollectionViewController檔案後就會自動幫忙加上 protocol所需要的function
將元件與 controller連結
將在 cell中的 imageView連到 PhotoCollectionViewCell檔案,命名為photoImageView
class PhotoCollectionViewCell: UICollectionViewCell { @IBOutlet weak var photoImageView: UIImageView!}
將 Selected Photo View Controller中的 imageView連到 Selected Photo View Controller檔案,命名為 ShowImageView
class SelectedPhotoViewController: UIViewController { @IBOutlet weak var ShowImageView: UIImageView!}
設定 collection view的 section與 item數量
這邊兩個 function:numberOfSections(in collectionView:)以及collectionView(numberOfItemsInSection:)會在 Collection View Controller的檔案裡面,但是回傳的數量要自己設定,在這裡我設定1個 section以及21個items(因為有21張圖片)
override func numberOfSections(in collectionView: UICollectionView) -> Int { return 1}override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 21}
設定 cell內容.大小.數量
使用 dequeueReusableCell來重複利用cell,以避免產生過多 cell造成記憶體不足(最多產生 view可見範圍+1),此處的 identifier就是先前所設定的 PhotoCollectionViewCell,使用 .self來確保沒打錯字
接著用 pic\(indexPath.row)與在 Assets.xcassets圖片的名字配對,第幾個 cell就會呈現出第幾張圖片
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "\(PhotoCollectionViewCell.self)", for: indexPath) as! PhotoCollectionViewCell cell.photoImageView.image = UIImage(named: "pic\(indexPath.row)") return cell}
設定cell的長跟寬
PhotoCollectionViewController 的 CollectionView中裡面Layout預設為 flow layout,所以能將它轉型為 CollectionViewFlowLayout,然後就能夠設定它的 itemSize 控制 cell 的尺寸
override func viewDidLoad() { super.viewDidLoad() // Register cell classes self.collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier) //設定cell的尺寸 //一排有三張image,且每一張圖片都一樣大,圖片間隔為1 let width = (collectionView.bounds.width - 1*2 ) / 3 //一行(直的)有四張image,每張圖一樣大,間隔為1
//若想要一行有?張,就除?,記得先減去間隔 let height = (collectionView.bounds.height - 1*3) / 4let flowLayout = collectionViewLayout as? UICollectionViewFlowLayout flowLayout?.itemSize = CGSize(width: width, height: height) //設定為0,cell的尺寸會依照itemSize調整,非0時是依照Auto layout flowLayout?.estimatedItemSize = .zero}
加上圖片
加上想要顯示的圖片
在 SelectedPhotoViewController設定想要接收到的資料以及顯示的畫面
由於要知道是選擇到第幾個圖片,所以傳來的資料是 Int
因為宣告 selectedPhotoIndex有加 ?,所以要用 if let打開
class SelectedPhotoViewController: UIViewController { @IBOutlet weak var ShowImageView: UIImageView! var selectedPhotoIndex:Int? override func viewDidLoad() { super.viewDidLoad() if let selectedPhotoIndex = selectedPhotoIndex{ ShowImageView.image = UIImage(named: "pic\(selectedPhotoIndex)") } else{ print("沒取得照片") } }}
使用 prepare(segue:)傳送資料
下一頁要跳到 SelectedPhotoViewController,因此要將 segue.destination轉換成 SelectedPhotoViewController,由於要將選擇到的行數傳送出去,使用indexPath(for: UICollectionViewCell).row來取得,在indexPath輸入要求的是 UICollectionViewCell,但是 sender是 Any?,所以將 sender強制轉型成UICollectionViewCell
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { let controller = segue.destination as? SelectedPhotoViewController let cell = sender as! UICollectionViewCell controller?.selectedPhotoIndex = self.collectionView!.indexPath(for: cell)?.row}
結果
結果圖
Github
參考
.self詳細說明