iOS UIKit Dynamics(物理碰撞,动画)

作者: 不误正业的开发者 | 来源:发表于2016-05-27 23:03 被阅读1266次

大部分人或许觉得动画用UIView 或是CoreAnimation的动画效果,那为何还需要UIKit 中的UIDynamic?
答:UIDynamic 为使用者提供更符合现实效果的互动行为(比如:自由落体能量消耗的过程)

一、需求:请实现下图所示的动画效果(物理碰撞)

JJ's Animation.gif

二、上面引入过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 ()<UICollisionBehaviorDelegate>

@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<UIDynamicItem>)item withBoundaryIdentifier:(id<NSCopying>)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

四、UIDynamicDemo:GitHub/jeversonjee点击下载

The last but not least:
1.如果想更好的玩转UIDynamics请查阅fancypixel有关Playing With UIDynamics in iOS 9
PS:1.录屏 Gif (for Mac)软件:GIPHY CAPTURE
2.那个boundary(边界)设置的适合下面的floor是一样高的,我选的图片是有白色背景的方形(Rect),没有把背景改成透明的,会感觉到球的底面没有和floor 重合的感觉。

相关文章

网友评论

本文标题:iOS UIKit Dynamics(物理碰撞,动画)

本文链接:https://www.haomeiwen.com/subject/uvlfdttx.html