en

hi, it seems you are using microsoft internet explorer. it doesn't match web standard and causes problems browsing this site. please please please use mozilla firefox or google chrome instead. thank you!

zh

哦哦!您正在使用Internet Explorer 瀏覽器,它與我們的網頁標準並不相容,可能會導致畫面顯示不正常。
請改用 Mozilla Firefox 或者 Google Chrome 才能正常瀏覽本網站,謝謝!

10.11.2013

關於 UIKit Dynamics 的二三事

  

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 協定的使用方式一文。





沒有留言:

張貼留言