UIKit Dynamics 是在 iOS 7 SDK 中才有的新東西,透過 UIKit Dynamics 我們能更容易的賦予 UIView 一些物理效果,像是受到重力掉落、UIView 彼此之間的反彈碰撞等等,如果你以前玩過 cocos2D 的 API,那你對這些物理效果一定不會感到陌生,下面我們將對 UIKit Dynamics 做些點單的說明,你可以在官方網站的 UIKit Dynamics Catalog 找到更多的範例說明。
UIKit Dynamics 基本架構
UIKit Dynamics 基本架構示意圖 |
上圖示意了 UIKit Dynamics 的基本結構,透過宣告一個 UIDynamicAnimator 來存放所要實作的物理行為 UIDynamicBehavior,並且針對每一個物理行為給予對應的 UIDynamicItem,而 UIDynamicAnimator 的 ReferenceView 則是指向所要呈現的 UIView。
例如,我們要在主要的 UIViewController 中實作出一個 myView(UIView)受到重力影響而落地的效果,ReferenceView 就是 [UIViewController View],而 UIDynamicItem 則是 myView。
最後,當你套用上物理效果之後,也別忘記將 UIView 透過 ReferenceView 的 addSubview: 函式加入到畫面中顯示。
ps:在實作上為了避免 ARC 機制自動釋放 UIDynamicAnimator 與 UIDynamicBehavior 的 Instance,建議可以將他們宣告在 @Interface 區段中,避免出現錯誤(下面的示範我們也都是先在 @Interface 區段中做好宣告)。
UIDynamicAnimator* animator;
UIGravityBehavior* gravity;
UICollisionBehavior* collision;
UIAttachmentBehavior *attachment;
UIPushBehavior *push;
UISnapBehavior* snap;
基本物理特性
基本物理特性上,包含重力、碰撞、吸附、推、甩與物理行為的限制等等,基本上它們的實作方法都大同小異,畢竟都是繼承於 UIDynamicBehavior 而來。
UIGravityBehavior
UIGravityBehavior 提供 UIView 受到重力影響而掉落的效果,UIView 會朝向畫面上 Y 軸較大的方向掉落,不受裝置的水平儀的影響。
//替self.view作UIDynamicBehavior的容器
animator = [[UIDynamicAnimator alloc] initWithReferenceView:[self view]];
//UIDynamicBehavior
gravity = [[UIGravityBehavior alloc] init];
[animator addBehavior:gravity];
//將myView套用具有重力的物理特性
[[self view] addSubview:myView];
[gravity addItem:myView];
UICollisionBehavior
UICollisionBehavior 可以讓 UIView 具有碰撞/反彈的物理特性,它的使用方法與上述相同,另外,如果你想要讓物件與 ReferenceView 的邊界也能發生碰撞效果,你可以將 setTranslatesReferenceBoundsIntoBoundary: 函式設定為 YES。
//能與ReferenceView邊界產生碰撞
[collision setTranslatesReferenceBoundsIntoBoundary:YES];
UICollisionBehavior 除了能夠讓 UIView 與 UIView 產生碰撞的效果外,它也可以定義一個範圍來產生碰撞的效果(有點像隱形的牆面)。
//以區域(demoLogo)來決定碰撞發生的位置
CGPoint p = CGPointMake(demoLogo.frame.origin.x +
demoLogo.frame.size.width, demoLogo.frame.origin.y);
[collision addBoundaryWithIdentifier:@"demoLogo"
fromPoint:demoLogo.frame.origin
toPoint:p];
上述程式碼我們使用 demologo 的所在位置當做區域來讓 UIView 產生碰撞,下圖為結果。
以自定範圍產生碰的結果 |
ps:如果你是在尋找UIView的之間的碰撞偵測,而非真的要實作碰撞的效果,請參考 Core Graphic 的碰撞偵測一文。
UIAttachmentBehavior
UIAttachmentBehavior 可以讓兩個 UIView 彼此互相牽制,你可以想像成將兩個 UIView 釘在木棍的兩端,它們在位移量上會彼此受到牽制。
attachment = [[UIAttachmentBehavior alloc] initWithItem:UIView_A
attachedToItem:UIView_B];
UIPushBehavior
UIPushBehavior 提供 UIView 朝向單方運動,它可以將運動量設定成瞬間與連續兩種(UIPushBehaviorModeInstantaneous / UIPushBehaviorModeContinuous)。
push = [[UIPushBehavior alloc] initWithItems:@[myView]mode:UIPushBehaviorModeInstantaneous];
//往右上角移動
[push setPushDirection:CGVectorMake(0.5, -0.5)];
[animator addBehavior:push];
UISnapBehavior
UISnapBehavior 能夠使 UIView 朝向目標點(CGPoint)甩出,並且包含瞬間的加速度,由慢而快,再由快變慢,最後停止於目標點。
CGPoint p = [[self view] center];
snap = [[UISnapBehavior alloc]initWithItem:myView snapToPoint:p];
[animator addBehavior:snap];
UIDynamicItemBehavior
UIDynamicItemBehavior 提供 UIView 在賦予物體特性的同時,又給予一些微調的限制參數,像是反彈係數、磨擦力、阻力等等。
UIDynamicItemBehavior* itemBehaviour = [[UIDynamicItemBehavior alloc] initWithItems:@[myView]];
[itemBehaviour setElasticity:1.0]; //反彈係數
[itemBehaviour setAllowsRotation:YES];//旋轉
[itemBehaviour setFriction:0.0]; //磨擦力
[itemBehaviour setResistance:0.0]; //阻力
[animator addBehavior:itemBehaviour];
取得 UIDynamicBehavior 發生的瞬間
所有的 UIDynamicBehavior 都可以透過 action 屬性的 Block 區塊來取得行為發生的瞬間。
[collision setAction:^{ }];
除了上述這個方法,在碰撞 UICollisionBehavior 你也可以透過引用 <UICollisionBehaviorDelegate> 協定來取得碰撞發生的位置、範圍的 Identifier 或 UIView的 Instance,來做更多的應用。
ps:有關協定的使用方法請參考 Protocol 協定的使用方式一文。
沒有留言:
張貼留言