UIDynamic 是iOS 7出现的一个新的特性,通过利用UIDynamic,我们可以在远离物理公式的计算下,通过简单的参数设置,能够实现一些复杂的动画效果。比如下面这样的。
如果需要自己动手写代码实现,这样的震动效果,估计不是非常的容易,效果可能也不太理想,但是用UIDynamic就非常容易了。
#import "ViewController.h"
@interface ViewController ()
//这个变量不能放在局部函数里面,必须是否则动画不会出现
@property (nonatomic,strong) UIDynamicAnimator * animator;
@property (nonatomic,strong) UIView * g_ball;
@end
@implementation ViewController
@synthesize g_ball;
- (void)viewDidLoad {
[super viewDidLoad];
g_ball = [[UIView alloc]initWithFrame:CGRectMake(100, 100, 50, 50)];
g_ball.backgroundColor = [UIColor redColor];
g_ball.layer.cornerRadius = 25;
[self.view addSubview:g_ball];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
UITouch * touch = [touches anyObject];
[self.animator removeAllBehaviors];
UISnapBehavior * snap = [[UISnapBehavior alloc]initWithItem:g_ball snapToPoint: [touch locationInView:self.view]];
snap.damping=0.4;//可以控制震动力度
[self.animator addBehavior:snap];
}
//
-(UIDynamicAnimator *)animator
{
if (!_animator) {
// 创建物理仿真器(ReferenceView : 仿真范围)
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
}
return _animator;
}
//重力测试
-(void)testGravity
{
//创建两个UI控件
UIView * ball = [[UIView alloc]initWithFrame:CGRectMake(100, 100, 50, 50)];
ball.backgroundColor = [UIColor greenColor];
ball.layer.cornerRadius = 25;
[self.view addSubview:ball];
//创建物理仿真行为中的重力行为,用两个UI控件对这个行为进行初始化,表示这两个控件需要用到重力行为
UIGravityBehavior * grav = [[UIGravityBehavior alloc]initWithItems:@[ball]];
// 设定重力加速度的方向,M_PI_2 是垂直向下 grav.gravityDirection
grav.angle = M_PI_4;
// 加速度的大小,1.0表示1000points/s^2
grav.magnitude=1;
[self.animator addBehavior:grav];
}
//碰撞测试
-(void)testCollision
{
//创建两个UI控件
UIView * ball = [[UIView alloc]initWithFrame:CGRectMake(100, 100, 50, 50)];
ball.backgroundColor = [UIColor greenColor];
ball.layer.cornerRadius = 25;
[self.view addSubview:ball];
UIView * board = [[UIView alloc]initWithFrame:CGRectMake(50, 200, 320, 50)];
board.backgroundColor = [UIColor redColor];
[self.view addSubview:board];
UIGravityBehavior * grav = [[UIGravityBehavior alloc]initWithItems:@[ball,board]];
UICollisionBehavior * collision = [[UICollisionBehavior alloc]initWithItems:@[ball,board]];
/**
这些事添加边界的方法:添加边界可以让碰撞发生在一定的范围
-(void)addBoundaryWithIdentifier:(id<NSCopying>)identifier
forPath:(UIBezierPath*)bezierPath;
-(void)addBoundaryWithIdentifier:(id<NSCopying>)identifier
fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2; ● -(UIBezierPath*)boundaryWithIdentifier:(id
<NSCopying>)identifier;
-(void)removeBoundaryWithIdentifier:(id<NSCopying>)identifier;
@property(nonatomic,readonly,copy)NSArray* boundaryIdentifiers;
-(void)removeAllBoundaries;
*/
//这个属性是确定是否以参照视图的bounds为边界
collision.translatesReferenceBoundsIntoBoundary=YES;
//这里也可以设置距离参照视图的内边距
[collision setTranslatesReferenceBoundsIntoBoundaryWithInsets:UIEdgeInsetsMake(10, 10, 10, 10)];;
//设置碰撞模式
/**
UICollisionBehaviorModeItems = 1 << 0, 元素碰撞
UICollisionBehaviorModeBoundaries = 1 << 1, 边界碰撞
UICollisionBehaviorModeEverything = NSUIntegerMax 全体碰撞(物体相互碰撞 边界也相互碰撞)
*/
collision.collisionMode = UICollisionBehaviorModeEverything;
//添加重力和撞击效果。
[self.animator addBehavior:collision];
[self.animator addBehavior:grav];
}
<p class="p1"><span class="s1">//</span><span class="s2">推动行为测试</span></p><p class="p2"><span class="s2">-(</span><span class="s3">void</span><span class="s2">)testPush</span></p><p class="p2"><span class="s2">{</span></p><p class="p1"><span class="s4"> </span><span class="s1">//</span><span class="s2">模式可以选择连续推动还是瞬间</span></p><p class="p3"><span class="s5"> </span><span class="s6">UIPushBehavior</span><span class="s5"> * push = [[</span><span class="s6">UIPushBehavior</span><span class="s5"> </span><span class="s2">alloc</span><span class="s5">]</span><span class="s2">initWithItems</span><span class="s5">:</span><span class="s7">@[</span><span class="s8">g_ball</span><span class="s7">]</span><span class="s5"> </span><span class="s2">mode</span><span class="s5">:</span><span class="s2">UIPushBehaviorModeInstantaneous</span><span class="s5">];</span></p><p class="p2"><span class="s2"> [</span><span class="s3">self</span><span class="s2">.</span><span class="s8">animator</span><span class="s2"> </span><span class="s9">addBehavior</span><span class="s2">:push];</span></p><p class="p4"><span class="s5"> </span><span class="s2">UICollisionBehavior</span><span class="s5"> * collision = [[</span><span class="s2">UICollisionBehavior</span><span class="s5"> </span><span class="s9">alloc</span><span class="s5">]</span><span class="s9">initWithItems</span><span class="s5">:</span><span class="s7">@[</span><span class="s8">g_ball</span><span class="s7">]</span><span class="s5">];</span></p><p class="p4"><span class="s5"> collision.</span><span class="s2">translatesReferenceBoundsIntoBoundary</span><span class="s5">= </span><span class="s3">YES</span><span class="s5">;</span></p><p class="p2"><span class="s2"> [</span><span class="s3">self</span><span class="s2">.</span><span class="s8">animator</span><span class="s2"> </span><span class="s9">addBehavior</span><span class="s2">:collision];</span></p><p class="p2"><span class="s2"> push.</span><span class="s6">angle</span><span class="s2"> = </span><span class="s10">M_PI</span><span class="s2">/</span><span class="s7">4</span><span class="s2">;</span><span class="s11">//</span><span class="s12">推的角度。</span></p><p class="p2"><span class="s2"> push.</span><span class="s6">magnitude</span><span class="s2"> = </span><span class="s7">10</span><span class="s2">;</span><span class="s11">//</span><span class="s12">推的力度</span></p><p class="p5"><span class="s5"> push.</span><span class="s6">active</span><span class="s5">=</span><span class="s3">YES</span><span class="s5">;</span><span class="s2">//</span><span class="s13">单次推动必须设置为</span><span class="s2">YES</span></p><p class="p2"><span class="s2">}</span></p>
@end