本文涉及到的WWDC2013 Session有 1.Session 206 Getting Started with UIKit Dynamics 2.Session 221 Advanced Techniques with UIKit Dynamics 什麼是UIKit動力學(UIKit Dyna ...
本文涉及到的WWDC2013 Session有 1.Session 206 Getting Started with UIKit Dynamics 2.Session 221 Advanced Techniques with UIKit Dynamics 什麼是UIKit動力學(UIKit Dynamics) 其實就是UIKit的一套動畫和交互體系。我們現在進行UI動畫基本都是使用CoreAnimation或者UIView animations。而UIKit動力學最大的特點是將現實世界動力驅動的動畫引入了UIKit,比如重力,鉸鏈連接,碰撞,懸掛等效果。一言蔽之,即是,將2D物理引擎引入了人UIKit。需要註意,UIKit動力學的引入,並不是以替代CA或者UIView動畫為目的的,在絕大多數情況下CA或者UIView動畫仍然是最優方案,只有在需要引入逼真的交互設計的時候,才需要使用UIKit動力學它是作為現有交互設計和實現的一種補充而存在的。 目的當然是更加自然和炫目的UI動畫效果,比如模擬現實的拖拽和彈性效果,放在以前如果單用iOS SDK的動畫實現起來還是相當困難的,而在UIKit Dynamics的幫助下,複雜的動畫效果可能也只需要很短的代碼(基本100行以內…其實現在用UIView animation想實現一個不太複雜的動畫所要的代碼行數都不止這個數了吧)。總之,便利多多,配合UI交互設計,以前很多不敢想和不敢寫(至少不敢自己寫)的效果實現起來會非常方便,也相信在iOS7的時代各色使用UIKit動力學的應用的在動畫效果肯定會上升一個檔次。 那麼,應該怎麼做呢? UIKit動力學實現的結構 為了實現動力UI,需要註冊一套UI行為的體系,之後UI便會按照預先的設定進行運動了。我們應該瞭解的新的基本概念有如下四個: UIDynamicItem:用來描述一個力學物體的狀態,其實就是實現了UIDynamicItem委托的對象,或者抽象為有面積有旋轉的質點; UIDynamicBehavior:動力行為的描述,用來指定UIDynamicItem應該如何運動,即定義適用的物理規則。一般我們使用這個類的子類對象來對一組UIDynamicItem應該遵守的行為規則進行描述; UIDynamicAnimator:動畫的播放者,動力行為(UIDynamicBehavior)的容器,添加到容器內的行為將發揮作用; ReferenceView:等同於力學參考系,如果你的初中物理不是語文老師教的話,我想你知道這是啥..只有當想要添加力學的UIView是ReferenceView的子view時,動力UI才發生作用。 光說不練假把式,來做點簡單的demo吧。比如為一個view添加重力行為:
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- UIView *aView = [[UIView alloc] initWithFrame:CGRectMake(100, 50, 100, 100)];
- aView.backgroundColor = [UIColor lightGrayColor];
- [self.view addSubview:aView];
- UIDynamicAnimator* animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
- UIGravityBehavior* gravityBeahvior = [[UIGravityBehavior alloc] initWithItems:@[aView]];
- [animator addBehavior:gravityBeahvior];
- self.animator = animator;
- }
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- UIView *aView = [[UIView alloc] initWithFrame:CGRectMake(100, 50, 100, 100)];
- aView.backgroundColor = [UIColor lightGrayColor];
- [self.view addSubview:aView];
- UIDynamicAnimator* animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
- UIGravityBehavior* gravityBeahvior = [[UIGravityBehavior alloc] initWithItems:@[aView]];
- [animator addBehavior:gravityBeahvior];
- UICollisionBehavior* collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[aView]];
- collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
- [animator addBehavior:collisionBehavior];
- collisionBehavior.collisionDelegate = self;
- self.animator = animator;
- }
- aView.transform = CGAffineTransformRotate(aView.transform, 45);
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- UIDynamicAnimator* animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
- UICollisionBehavior* collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[self.square1]];
- collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
- [animator addBehavior:collisionBehavior];
- UIGravityBehavior *g = [[UIGravityBehavior alloc] initWithItems:@[self.square1]];
- [animator addBehavior:g];
- self.animator = animator;
- }
- -(IBAction)handleAttachmentGesture:(UIPanGestureRecognizer*)gesture
- {
- if (gesture.state == UIGestureRecognizerStateBegan){
- CGPoint squareCenterPoint = CGPointMake(self.square1.center.x, self.square1.center.y - 100.0);
- CGPoint attachmentPoint = CGPointMake(-25.0, -25.0);
- UIAttachmentBehavior* attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:self.square1 point:attachmentPoint attachedToAnchor:squareCenterPoint];
- self.attachmentBehavior = attachmentBehavior;
- [self.animator addBehavior:attachmentBehavior];
- } else if ( gesture.state == UIGestureRecognizerStateChanged) {
- [self.attachmentBehavior setAnchorPoint:[gesture locationInView:self.view]];
- } else if (gesture.state == UIGestureRecognizerStateEnded) {
- [self.animator removeBehavior:self.attachmentBehavior];
- }
- }
- //GravityWithCollisionBehavior.h
- @interface GravityWithCollisionBehavior : UIDynamicBehavior
- -(instancetype) initWithItems:(NSArray *)items;
- @end
- //GravityWithCollisionBehavior.m
- @implementation GravityWithCollisionBehavior
- -(instancetype) initWithItems:(NSArray *)items
- {
- if (self = [super init]) {
- UIGravityBehavior *gb = [[UIGravityBehavior alloc] initWithItems:items];
- UICollisionBehavior *cb = [[UICollisionBehavior alloc] initWithItems:items];
- cb.translatesReferenceBoundsIntoBoundary = YES;
- [self addChildBehavior:gb];
- [self addChildBehavior:cb];
- }
- return self;
- }
- @end