【iOS】#12 照片編輯軟體 Part1: 剪裁、旋轉、鏡射
Collection View, instantiateViewController, touch event, UIGraphicsImageRenderer
本篇提及的功能有:
Collection View 照片牆
instantiateViewController 不用 segue 切畫面並傳資料
touch event 偵測點擊行為
UIGraphicsImageRenderer 儲存 view 為 UIImage 圖片
APP 構想
這次要製作的是照片編輯軟體,想要實作的功能有:
- 圖片旋轉、鏡射
- 剪裁圖片
- 重設圖片
- 分享照片
- 儲存照片
- 上濾鏡
- 貼上文字
這次會先實作前三個基本功能,之後再來製作其他的功能
APP wireframe
總共有三個畫面;第一個畫面放置編輯過後的照片,用 collection view 呈現
點擊第一頁下方新增按鈕,叫出相簿讓使用者選擇欲編輯的照片
進到第三頁,即為編輯頁面,最下排是主功能選單。點擊不同的主功能,依照需求跳出次功能列
編輯頁面上方可以放棄編輯返回第一頁,亦可重設編輯或者儲存照片
選擇儲存照片的話,將會把目前的編輯照片呈現於第一頁的 collection cell 中
APP 實作問題
Collection View 設定
運用 Collection View 的方法有幾種,我使用的是 View Controller 中添加 Collection View
首先需要把 Collection View 的 dataSource 連結到他所在的 View Controller 上
接著在 View Controller class 上加上代理 UICollectionViewDataSource 與 UICollectionViewDelegate
接下來把需要實作的協定設定一下
這裡我用 imageCollection 存照片牆要出現的 UIImage,numberOfItemsInSection 是該 section 要呈現的 item 數量,所以就直接回傳 imageCollection 陣列元素的數量
上方第二個 function 是設定每個 Cell 要出現的內容。先在 Storyboard 上設定Cell 的 id
withReuseIdentifier 需要跟 Storyboard 上設定的 id 一樣,這樣程式才知道要呈現哪種型態
然後為了呈現圖片,自訂一個 UIImageView 在 Cell 中,拉 IBOutlet 到自訂義的 class 中
最後把 cellImageView 裝入相對應 imageColletion 中的照片即可完成
定義 Collection Layout
預設的 Cell 有點小,要自己定義大小與間距的話,需要 UICollectionViewFlowLayout 的幫忙
collectionLayout.sectionInset = UIEdgeInsets(top:5, left: 5, bottom: 5, right: 5)collectionLayout.itemSize = CGSize(width: fullScreenSize.width/3-10, height: fullScreenSize.width/3-10)collectionLayout.minimumLineSpacing = 5collectionLayout.scrollDirection = .verticalcollectionLayout.headerReferenceSize = CGSize(width: fullScreenSize.width, height: 24)
sectionInset: 設定 Section 間距
itemSize: 設定每個 Cell 的大小
minmumLineSpacing: Cell 的間距
scrollDirection: 滑動的方向
headerReferenceSize: 設定 Section Header 的大小
不過這邊需要把 Collection View 的 Estimate Size 關掉,預設的 Automatic 會自己設定 item 大小,自定義會失效
instantiateViewController 傳資料給下一頁
instantiateViewController 可以不用在 storyboard 上建立 segue 就切到下一頁
不過如果要傳初始資料給第二頁的話,需要用 creator
if let retouchController = storyboard?.instantiateViewController(identifier: "retouchViewController", creator: { coder in RetouchViewController(coder: coder, editImage: image!)}) { show(retouchController, sender: nil)}
touch event 偵測點擊行為
在剪裁照片的部分,希望透過拖拉圖片角落的方式,拉出想要的範圍
參考 Stackoverflow 的解法~
UIView 有提供 touchesBegan, touchesMoved, touchesEnded 等 function,監聽事件去執行行為
原理就是根據使用者拖拉的初始點、拖拉的距離,來變動 view 的位置與大小,達到剪裁的效果
UIGraphicsImageRenderer 儲存 view 為 UIImage 圖片
編輯完的照片,要擷取 view 呈現的畫面為圖片,可以使用 UIGraphicsImageRenderer
let renderer = UIGraphicsImageRenderer(size: editImageView!.bounds.size)let image = renderer.image(actions: { (context) in editImageView!.drawHierarchy(in: editImageView!.bounds, afterScreenUpdates: true)})// 存入 imageCollection
imageCollection.append(image)// 回到第一頁
navigationController?.popToRootViewController(animated: true)
APP Demo
參考資料
圖片翻轉、鏡射
instantiateViewController 傳資料
collection view 照片牆
view 轉為圖片
AutoLayout 刷新動畫