#27 實作 Collection View | 吉卜力照片牆

去年新開幕的吉卜力公園,太讓人瘋狂啦!共分三階段開放,第一彈就是去年的11/1日!But…去之前務必做好功課,例如前三個月就得預約入門票🥺就用想去的心來做這次的作業吧~

⬇️成品預覽

✏️ App 功能

  • UICollectionView
  • UICollectionViewDataSource
  • IBSegueAction
  • URLSession
  • UIActivityIndicatorView
  • viewDidAppear

✏️ 程式說明

製作基本版的照片牆,按下想看的卡通圖集,以格子狀顯示圖片,下ㄧ頁顯示大圖

1. 以格子狀顯示時,可設定一排顯示幾個/間距/行距等

其中使用 floor 計算可得到整數,若有小數可能就會超出畫面進到下一行

func configureCellSize(){
let itemSpace: Double = 3 // cell間距
let columeCount:Double = 3 // 一排有幾個cell
let flowLayout = collectionViewLayout as? UICollectionViewFlowLayout
let width = floor((collectionView.bounds.width - itemSpace * (columeCount-1)) / columeCount)
//計算完為整數.若有小數可能就會超出畫面進到下一行,(螢幕寬-cell間距數量)/cell數量
flowLayout?.itemSize = CGSize(width: width, height: width)
flowLayout?.estimatedItemSize = .zero
flowLayout?.minimumLineSpacing = itemSpace //上下間距
flowLayout?.minimumInteritemSpacing = itemSpace //左右間距
}

2. 上網抓圖片

在getImageFromUrl 的 completion 加上@escaping,可讓getImageFromUrl 的 closure 在 function 執行後繼續使用

func getImageFromUrl(url:URL?, completion: @escaping (UIImage?) -> Void) {
if let url{
URLSession.shared.dataTask(with: url) { data, response, error in
if let data,
let image = UIImage(data: data) {
DispatchQueue.main.async {
self.collectionView.reloadData()
}
completion(image)
}else{
completion(nil)
}
}.resume()
}
}
func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?,
Error?) -> Swift.Void) -> URLSessionDataTask

getImageFromUrl 的 completion 會在 dataTask 的 completionHandler 裡使用,function在執行時,會先呼叫task的resume( )來啟動,等資料抓到時才會執行 completionHandler

如果 completion 沒有加 @escaping ,它在 function getImageFromUrl 執行完的時候就不能再呼叫了

當參數有使用@escaping時,存取方法或屬性時需加上self

3. 抓圖的網址格式

func getImages(){
for imageNumber in 1...50 {
let imageNo = String(format: "%03d", imageNumber)
// https://www.ghibli.jp/works/totoro/#&gid=1&pid=1 (totoro001)
if let url = URL(string: "https://www.ghibli.jp/gallery/\(imageName)\(imageNo).jpg") {
getImageFromUrl(url: url) { image in
if let image {
self.images.append(image)
// print("photo")
}
}
}
}
}

圖片編號為1–50,以%03d呈現

% 是格式符的开始; d 表示有符号為整數; 3 表示輸出三位數字; 0 表示如果數字不足3位,在左邊用0補成3位

4. 上網抓圖會有空檔時間,利用UIActivityIndicatorView,呈現等待中的loading狀態

//畫面載入完成時
override func viewDidLoad() {
super.viewDidLoad()
configureCellSize()
addLoadingView()-->呼叫UIActivityIndicatorView的startAnimating()
navigationItem.title = movieTitle

}

//更新畫面後才開始抓圖,抓完後移除loadingView
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
getImages()
loadingView.removeFromSuperview()
}

吉卜力工作室開放下載高清圖片,超適合用來做這次的作業的!😆

🔆GitHub

📝參考文章

--

--