[study#9-1] 製作拍立得 App 學習

模仿照片比例及生成拍立得照片

畫面1的比例顯示,我有加一張未裁切照片原圖,調整半透明後放在底部。

為了顯示選擇比例時,照片是裁切而不縮放,我在中間加了一個subView,並將imageView放進subView中。

imageView需與orgineView大小位置完全重疊,因此

imageView的x =負的 subView的x

imageView的y =負的(subView的y — originView的y)

由於subView的位置是置中放置,所以

subView的x = (view的width — subView的width)/2

因此 imageView的x

又可以= — (view的width — subView的width)/2

呈現效果可以如下:

if else的部分不複雜,x, y的數值比較需要思考配置一下

...  var width: CGFloat = 375  var height: CGFloat = 375  if sender.currentTitle == "1 : 1" {    ratio = "3 : 4"    width = 275    height = width / 3 * 4  }  else if sender.currentTitle == "3 : 4" {    ratio = "16 : 9"    width = 275    height = width / 16 * 9  }  else {    ratio = "1 : 1"    width = 275    height = width  }sender.setTitle(ratio, for: UIControl.State.normal)subView.frame = CGRect(x: (view.frame.width-width)/2, y: 120+(view.frame.width-height)/2, width: width, height: height)imageView.frame = CGRect(x: -(view.frame.width-width)/2, y: -(view.frame.width-height)/2, width: 375, height: 375)

p.s.我使用的image是方形圖,計算xy與尺寸都更為方便

畫面2基本上也是直接複製畫面1的,但多加了一個拍立得相片的空白view

同時,subView是放入blankView(空白View)之中的

因應此改變,subView.frame.x 會變成

(blankView的width — subView的width)/2

...massageLabel.text = photoTextvar width: CGFloat = 375var height: CGFloat = 375if ratio == "1 : 1" {  width = 275  height = width}else if ratio == "3 : 4" {  width = 275  height = width / 3 * 4}else if ratio == "16 : 9" {  width = 275  height = width / 16 * 9}blankView.frame.size.height = height + 110subView.frame = CGRect(x: (blankView.frame.width-width)/2, y: 20, width: width, height: height)imageView.frame = CGRect(x: -(view.frame.width-width)/2, y: -(view.frame.width-height)/2, width: 375, height: 375)massageLabel.frame.origin.y = subView.frame.maxY + 5

frame的寫法:

一開始寫的方式是

xxxView.frame = CGRect(x: 100, y: 200, width: 300, height: 400)

後來發現也可以這樣寫

xxxView.frame.origin.x = 100

xxxView.frame.origin.y = 200

xxxView.frame.size.width = 300

xxxView.frame.size.height = 400

差別是第一種必須全寫,第二種可以針對單個編寫

動畫:

空白View的部分,動畫呈現採用 高度從0開始隨時間變長的方式。

動畫也有位置移動的方式,所以imageView跟label就試著使用位置動畫。

let blankViewHight = self.blankView.frame.size.heightlet massageY = massageLabel.frame.origin.ylet subViewY = massageY - 5 - subView.frame.heightself.blankView.frame.size.height = 0self.massageLabel.frame.origin.y = -85self.subView.frame.origin.y = -90 - subView.frame.height
UIView.animate(withDuration: 2) {self.blankView.frame.size.height = blankViewHightself.massageLabel.frame.origin.y = massageYself.subView.frame.origin.y = subViewY}

寫在UIView.animate(){ }裡面的,是動畫最後的結果;

寫在UIView.animate上方的,是動畫的開始;

想像一下最後的位置跟開始的位置會像以下,
紫色是最後的位置,灰色是開始的位置

blankView的height 是 subView的height 加110

又subView的y 為20, label的y 為subView的maxY加5

所以label的y距離blankView的maxY 恆為85

因此動畫開始時,label的位置

self.massageLabel.frame.origin.y = -85

subView的位置

self.subView.frame.origin.y = -90 - subView.frame.height

堅持拍立得印出照片的目標,總算也把期望的動畫做出來了!

專案內容:

--

--

Yolanda H.
彼得潘的 Swift iOS / Flutter App 開發教室

悠琅妲之愛梯熙緹推敲推敲潑墨坊 { iOS App | website SEO | Python | Aroma | Zumba | Chinese Poems | Tabletop game }