UIDynamicAnimator :為我們提供了一些基于物理學的動畫,讓我們更容易的做出一些與現(xiàn)實世界(物理行為)相符的逼真的二維動畫。
iOS 7 之后,Apple 給我們提供了一個與物理學相關(physics-related)的 API,與之相關的有兩個類和一個協(xié)議:
-
UIDynamicAnimator- 動畫生成器,我們只需配置好屬性并提交給它,其余的由它去做。 -
UIDynamicBehavior- 一些物理學行為。它的子類提供了一些具體的物理學行為。 -
UIDynamicItem- 這是一個協(xié)議,只要遵循了這個協(xié)議的任何對象, 都可以成為UIDynamicAnimator動畫的對象。UICollectionViewLayoutAttributes,UIDynamicItemGroup(iOS 9.0 +),UIView都遵循了這個協(xié)議。
一張圖更好的理解:

UIDynamicAnimator
它像一個驅(qū)動類,它關聯(lián)了遵守UIDynamicItem協(xié)議的可動畫對象Item和行為Behavior,給動畫的執(zhí)行提供了上下文,之后動畫的執(zhí)行由它驅(qū)動。它有類似于集合的一些方法:- addBehavior:,- removeBehavior:,- removeAllBehaviors.
其中,需要注意的有幾點:
- 初始化方法:
- initWithReferenceView:中傳入的是參考view,而不是直接動畫的view。 - 動畫執(zhí)行完畢后,可動畫對象的一些屬性會被改變而不會復原(frame、color、size and so on...)。所以,如果我們需要重復執(zhí)行一個動畫的話,我們需要在合適的時機重新設置這些值。
APIs
UIDynamicAnimator的API只有幾個,如下:

UIDynamicBehavior
提供動畫行為的類。使用中我們更多的是直接使用他的子類。子類具體如圖1所示。它的子類實現(xiàn)了各種物理學行為。具體可以查看每個子類的頭文件。他們有幾個通用的屬性:

UIAttachmentBehavior
Discussion
UIAttachmentBehavior可以把兩個view或者view 和 anchorPoint 關聯(lián)起來。
APIs
它有一些自己的屬性,其中比較重要的是:
-
damping: 阻尼,要和阻力做區(qū)分,當此值設置為1時,達到臨界阻尼,到達臨界阻尼后我們的動畫便不再會有回彈的效果。 -
frequency: 頻率,行為的頻率,單位Hz,值越大,頻率越高,動畫過程越快,動畫效果越不明顯。 -
length: 關聯(lián)的兩個對象(view和view或者view和anchorPoint) 動畫結束后兩者錨點(anchor)之間的距離長度。 -
frictionTorque: 摩擦力矩,作用暫時不詳。
demo
基于蘋果爸爸強大的封裝,我們可以很容易的實現(xiàn)下面的效果:

完整的代碼為:
UIAttachmentBehavior *attachment = [[UIAttachmentBehavior alloc] initWithItem:self.animationView attachedToItem:self.relyView];
attachment.damping = 0.5;
attachment.frequency = 1.f;
attachment.length = 80;
// attachment.frictionTorque = 1.f;
attachment.action = ^{
NSLog(@"%@",NSStringFromCGRect(self.animationView.frame));
};
[self.animator addBehavior:attachment];
你可以自己調(diào)整下參數(shù),看看之后的效果。
UIGravityBehavior
Discussion
UIGravityBehavior模擬的是現(xiàn)實生活中的重力特性。

APIs
能讓我們自定義的API只有幾個,其中:
-
gravityDirection: 重力方向。單位向量,默認是(0.0,1.0),即重力向下。重力坐標系和UIKit的一樣。y軸向下為正,x軸向左為正。如下:

UICollisionBehavior
Discussion
UICollisionBehavior模擬的是現(xiàn)實生活中的碰撞特性。在碰撞中,我們需要指定碰撞的邊界,碰撞的邊界可以是另一個view,可以是一個邊界。如果我們沒有指定邊界的話, 并且也沒有將參考視圖作為邊界,那么碰撞行為就不會發(fā)生。

APIs
-
collisionMode: 指定碰撞的邊界類型。 -
translatesReferenceBoundsIntoBoundary: 把參考視圖轉(zhuǎn)化為碰撞的邊界。 -
- addBoundaryWithIdentifier:forPath::指定一個貝塞爾路徑作為碰撞邊界,并給這個碰撞邊界一個標記。 -
- addBoundaryWithIdentifier:fromPoint:toPoint:指定兩個點之間的連線為碰撞邊界。如果指定collisionMode為UICollisionBehaviorModeItems,則設置這個屬性無效。
UIPushBehavior
Discussion
UIPushBehavior可以對一個物體施加一個連續(xù)的或者瞬時的力,并改變物體的位置。

APIs
-
UIPushBehaviorMode:推力的類型,枚舉值。分為持續(xù)(UIPushBehaviorModeContinuous)和瞬時(UIPushBehaviorModeInstantaneous)。 -
angle: 推力的角度。 -
magnitude: 推力的大小。 -
pushDirection: 推力的方向,和UIKit的坐標系相同。 -
active: 推力當前的狀態(tài),分為active和inactive.
SnapViewController
Discussion
UISnapBehavior模擬的是物體吸附的行為,并且伴有彈簧動畫。

APIs
-
damping: 阻尼。 -
snapPoint: 和anchorPoint的作用類似,代表的是當前Item的錨點位置。
UIDynamicItemBehavior
如果你不滿足于上面的屬性,那么UIDynamicItemBehavior給你提供了更多的選擇。我們可以使用UIDynamicItemBehavior,來設置Item的更多屬性。包括:
elasticity: 彈力。在0~1之間,0代表無彈性,1代表彈性碰撞friction: 摩擦力。charge: 電荷。決定了物體和電場或者磁場之間的相互作用力。density: 密度。決定了動力項的其他屬性的表現(xiàn),比如摩擦、碰撞等。angularResistance: 角度阻力。有效范圍在0~CGFlOAT_MAX,值越大,在動力行為中物體越不容易旋轉(zhuǎn)。resistance: 阻力。動力項的線性阻力。有效值范圍為0.0~CGFLOAT_MAX。anchored: 是否固定錨點。如果這個值為YES,那么,當發(fā)生碰撞的時候,物體不會移動,但參與碰撞。效果類似于一個碰撞邊界。- addLinearVelocity:forItem:: 給物體增加一個線性速度。- addAngularVelocity:forItem:: 給物體增加一個角速度。allowsRotation: 值為NO時,強制物體再發(fā)生碰撞之后不會旋轉(zhuǎn)。
小結
這是 Apple 在 iOS 7推出的功能,在iOS 9之后增加了一些新的API。算是一個老功能,現(xiàn)在才研究起來算是補作業(yè)了?;径际歉鶕?jù)官方文檔摸索著寫的一個小Demo,實現(xiàn)了一些基本的小效果。更加炫酷的就需要靠強大的 idea 了。