一、需求:請實現下圖所示的動畫(物理碰撞)
二、上面引入過UIDynamic 可以實現碰撞的物理效果動畫,how to start ?
在工程中導入UIKit,從Headers 找一些UIDynamic,發現了UIDynamicAnimator.h,UIDynamicBehavior,UIDynamicItemBehavior
既然是要動畫效果 那就應該是UIDynamicAnimator.h
到UIDynamicAnimator.h 頭文件去查看注釋
// When you initialize a dynamic animator with this method, you should only associates views with your behaviors. // the behaviors (and their dynamic items) that you add to the animator employ the reference view’s coordinate system. - (instancetype)initWithReferenceView:(UIView *)view NS_DESIGNATED_INITIALIZER;
大概意思是使用這個初始化方法的時候,需要為你的試圖關聯behaviors
what’s the behaviors ? jump into defination 然而還不是很懂,UIDynamicBehavior,那就查看API (注意文檔中的如下描述)。
This parent class, UIDynamicBehavior, is inherited by the primitive dynamic behavior classes UIAttachmentBehavior, UICollisionBehavior, UIGravityBehavior, UIDynamicItemBehavior, UIPushBehavior, and UISnapBehavior.
文檔中提到UIDynamicBehavior的父類,那麼UIDynamicBehavior父類(Dynamic 行為相關類)描述什麼行為呢?
UIAttachmentBehavior:附著行為
UICollisionBehavior:碰撞行為
UIGravityBehavior:重力行為
UIDynamicItemBehavior:動態元素行為
UIPushBehavior:推行為
UISnapBehavior:吸附行為
上述的各種行為可單獨使用,也可以組合使用更復雜的動畫效果。
解決方案的思路就引導到這邊,也就可以實現上述需求。Dynamic 行為相關類的屬性可自行研究。
三、解決方案。
上述需求的解決方案(我這邊用的是6sP的模擬器奧,因為在設置floor的y坐標是600)
既然是球落地效果,必然有兩個模擬對象:floor,basketBall
1.創建UIDynamicAnimator 對象
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
2.剛剛在API 看到了初始化UIDynamicAnimator需要關聯一個或者多個行為
NSArray *animatorObjects = @[self.imageV1]; // 剛剛在API 看到了初始化UIDynamicAnimator需要關聯一個或者多個行為 self.gravityBehav = [[UIGravityBehavior alloc] initWithItems:animatorObjects]; self.colision = [[UICollisionBehavior alloc] initWithItems:animatorObjects];
3.如果你想監聽碰撞的狀態,可以設置一下代理
self.colision.collisionDelegate = self;
4.設置碰撞邊界
[self.colision addBoundaryWithIdentifier:@"boundaryLine" fromPoint:CGPointMake(0, 600) toPoint:CGPointMake(SCREENWITH, 600)];
5.設置動態行為參數
// 設置動態行為參數 UIDynamicItemBehavior *itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:animatorObjects]; // 設置彈性 [itemBehavior setElasticity:0.5];
6.行為創建了,別忘了給animator添加上
[self.animator addBehavior:self.gravityBehav]; [self.animator addBehavior:self.colision]; [self.animator addBehavior:itemBehavior];
三、下面代碼只能說功能實現
PS:以下代碼不符合代碼書寫規范
// // ViewController.m // DynamicAnimation // // Created by JeversonJee on 16/5/27. // Copyright © 2016年 JeversonJee. All rights reserved. // #import "ViewController.h" #define SCREENWITH [UIScreen mainScreen].bounds.size.width #define SCREENHEIGHT [UIScreen mainScreen].bounds.size.height @interface ViewController () @property (nonatomic, strong) UIDynamicAnimator *animator; @property (nonatomic, strong) UIGravityBehavior *gravityBehav; @property (nonatomic, strong) UICollisionBehavior *colision; @property (nonatomic, strong) UIImageView *imageV1; @property (nonatomic, strong) UIImageView *imageV2; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self jjCollisionBehav]; } - (void)jjCollisionBehav { // 創建碰撞需要的對象 [self jjCreateBall]; [self jjCreateFloor]; // 創建UIDynamicAnimator 對象 self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; NSArray *animatorObjects = @[self.imageV1]; // 剛剛在API 看到了初始化UIDynamicAnimator需要關聯一個或者多個行為 self.gravityBehav = [[UIGravityBehavior alloc] initWithItems:animatorObjects]; self.colision = [[UICollisionBehavior alloc] initWithItems:animatorObjects]; // 這裡設置代理是為了監聽碰撞狀態的,可以去了解一下代理方法 self.colision.collisionDelegate = self; // 設置碰撞邊界 [self.colision addBoundaryWithIdentifier:@"boundaryLine" fromPoint:CGPointMake(0, 600) toPoint:CGPointMake(SCREENWITH, 600)]; // 設置動態行為參數 UIDynamicItemBehavior *itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:animatorObjects]; // 設置彈性 [itemBehavior setElasticity:0.5]; // 創建了行為需要animator添加 [self.animator addBehavior:self.gravityBehav]; [self.animator addBehavior:self.colision]; [self.animator addBehavior:itemBehavior]; } -(void)collisionBehavior:(UICollisionBehavior *)behavior endedContactForItem:(id)item withBoundaryIdentifier:(id)identifier { NSLog(@"collisionBehavior=%@", item); NSString *identifierStr = [NSString stringWithFormat:@"%@", identifier]; NSLog(@"s=%@", identifier); if ( [identifierStr isEqualToString:@"boundaryLine"] ) { [self.imageV2 setBackgroundColor:[UIColor grayColor]]; [UIView animateWithDuration:2 animations:^(void){ [self.imageV2 setBackgroundColor:[UIColor grayColor]]; }]; } } -(void)jjCreateBall { _imageV1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"basketBall"]]; _imageV1.frame = CGRectMake(100, 100, 60, 60); [self.view addSubview:_imageV1]; } - (void)jjCreateFloor { _imageV2 = [[UIImageView alloc] init]; [_imageV2 setBackgroundColor:[UIColor grayColor]]; _imageV2.frame = CGRectMake(0, 600, SCREENWITH, SCREENHEIGHT - 400); [self.view addSubview:_imageV2]; } -(void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end