CoreAnimation與UIView.animation...
這兩個方式的主要差別在于,前者如果不主動設置,那么在動畫做完以后,會恢復原狀。
后者則不會,動畫做完后是什么樣,控件就是什么樣。
UIView.animation...是什么
首先我們來做一個動畫
UIView.animate(withDuration: 5, animations: {self.moveView.frame.origin.y += 200
})
這個動畫是讓moveView在Y軸上移動200個點。
- 我們在動畫代碼前,打印一下這個控件的frame信息 (155.0, 140.0, 64.0, 64.0)
- 然后我們在動畫開始2秒和動畫結束時打印一下frame信息,讓人疑惑的是結果都為 (155.0, 340.0, 64.0, 64.0)
- 我們先停一下,去看看CoreAnimation
CoreAnimation
使用CA動畫時,主要是使用的CAAnimation的子類(下面簡稱 anim )。
anim 是添加到Layer上的,你可以在layer上訪問添加到該layer的 anim 。好的,現在我們做一個和上面一樣的Y軸上的位移動畫。
- 在動畫開始后的2秒打印一下frame和layer.frame信息,都是 (155.0, 140.0, 64.0, 64.0)
- 在2秒時打印animationKeys, Optional(["position"])
- 動畫結束后,控件恢復到了原狀,animationKeys為 nil
- 我們把anim改成動畫結束后保持結束時狀態再看看1-3點的信息
- frame和layer.frame信息,也還都是 (155.0, 140.0, 64.0, 64.0)
- 在2秒時打印animationKeys, Optional(["position"])
- 動畫結束后,控件恢復到了原狀,animationKeys為 Optional(["position"])
- 此時我們使用Xcode的視圖調試工具查看,控件位置在 (155.0, 140.0, 64.0, 64.0) ,并且調試界面的位置和APP上的位置完全不一樣。
CoreAnimation動畫的注意事項
怎么獲取正在移動時的位置呢,如果有一個需求是要拿到實際運動的位置,該怎么辦?
使用 presentation 屬性
在CA動畫里,所有的實時狀態都會反應到這個屬性返回的layer上,本體layer在動畫時會被 隱藏 !
- 現在我們根據剛才的 anim 動畫查看一下 presentation 的信息。
- 果然,控件位置的實時信息是反應在這個layer上的
回過來看UIView.animation...
我們在動畫進行時打印 presentation 的信息,打印的frame信息竟然能夠正確反應當前控件的位置情況。
我們再打印 animationKeys 信息看看, Optional(["position"]) 。
我想答案已經呼之欲出了。 UIView.animation... 使用的是 CoreAnimation 在做動畫,只是細節對程序員隱藏了。
兩者的區別上需要注意的地方
但是還有一個問題,剛才的打印結果,_UIView.animation..._ 結束后,frame信息為 (155.0, 340.0, 64.0, 64.0) ,而 anim 結束后為 (155.0, 140.0, 64.0, 64.0) ,但是 anim 的 presentation 的frame卻是正確的。
這意味著你如果要在 anim 動畫后讓控件移動到正確的位置,你需要把控件的frame也設置到正確到位置,而不只是在 anim 上設置。
那什么時候設置是一個正確到時機呢?我們注意到,在開始做動畫到時候,屏幕上現實的視圖,實際上是顯示的 presentation 的信息,而不依賴于控件本身的layer。所以在做動畫前后都能去設置控件本身到正確的屬性。