UIDynamic是从iOS7开始引入的技术 属于UIkit框架 可以模拟显示生活中的物理现象 如碰撞 抖动 摆动等
一.使用UIDynamic步骤:
1.创建一个动力效果器UIDynamicAnimator
2.创建动力效果(Behavior)添加到对于的视图上
3.将动力效果添加到动力效果器中
注:必须遵守了UIDynamicItem这个协议才可以使用动力效果,UIView默认已经遵守了UIDynamicItem协议
玩动力效果 如玩电吉他 电吉他有效果器 可以添加各种电子效果
动力效果 也有一个效果器 叫做 动力效果器 里面可以添加 动力效果
电吉他切换效果 会把上一个效果移除
动力效果 也是一样
电吉他可以叠加多个效果
动力效果 也是一样
UIDynamic提供的动力效果
二.重力效果的属性:
UIGravityBehavior:重力效果(设置重力的方向 加速度 让物体(视图)朝着重力方向掉落)
NSArray *items;添加到重力效果中的所有效果作用对象
CGVector gravityDirection;重力方向(是一个二维向量)以左上角为坐标原点 x 负数向左 正数向右 y 负数向上 正数向下 数字越大 重力效果越大
CGFloat angle;重力方向(是一个角度,x轴正方向为0°,顺时针正数,逆时针负数)
CGFloat magnitude;量级(用来控制加速度,1.0代表加速度是1000 points /second²)重力加速度越大 碰撞越厉害
UICollisionBehavior:碰撞效果()可以让物体之间实现碰撞效果, 也可以通过添加边界(boundary)在边界实现碰撞效果
边界相关的方法:
- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier forPath:(UIBezierPath*)bezierPath; 添加一个贝塞尔曲线路径的边界
- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2; 通过添加两个点连成的线 作为边界
- (UIBezierPath*)boundaryWithIdentifier:(id <NSCopying>)identifier; 通过ID找到边界路径
- (void)removeBoundaryWithIdentifier:(id <NSCopying>)identifier; 移除ID对应的边界
@property (nonatomic, readonly, copy) NSArray* boundaryIdentifiers; 边界数组
- (void)removeAllBoundaries;移除所有边界
typedef NS_OPTIONS(NSUInteger, UICollisionBehaviorMode) {
UICollisionBehaviorModeItems = 1 << 0,元素碰撞
UICollisionBehaviorModeBoundaries = 1 << 1,边界碰撞
UICollisionBehaviorModeEverything = NSUIntegerMax 全体碰撞
} NS_ENUM_AVAILABLE_IOS(7_0);
碰撞效果的代理方法:
//两个元素相互碰撞
- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p;
- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2;
// 视图碰撞边界的时候 触发
- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier atPoint:(CGPoint)p;
- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier;
三.具体代码
@interface ViewController ()<UIDynamicAnimatorDelegate,UICollisionBehaviorDelegate> { UIDynamicAnimator * dynamicAnimator; UIView * view1; UIView * view2; UIView * view3; } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 动力效果器 dynamicAnimator = [[UIDynamicAnimator alloc]initWithReferenceView:self.view]; // self.view 产生动力效果的区域 dynamicAnimator.delegate = self; view1 =[[UIView alloc]initWithFrame:CGRectMake(0,0,90 , 90)]; view1.center = self.view.center; view1.backgroundColor = [UIColor redColor]; [self.view addSubview:view1]; view2 =[[UIView alloc]initWithFrame:CGRectMake(0,0,90 , 90)]; view2.center = CGPointMake(self.view.center.x+100, self.view.center.y+100); view2.backgroundColor = [UIColor orangeColor]; [self.view addSubview:view2]; view3 =[[UIView alloc]initWithFrame:CGRectMake(0,0,90 , 90)]; view3.backgroundColor = [UIColor blueColor]; [self.view addSubview:view3]; }
#pragma mark -------手指触摸屏幕 添加动力效果-------------------------- -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch * touch = [touches anyObject]; CGPoint touchpoint = [touch locationInView:self.view]; view1.center = touchpoint; view2.center = CGPointMake(self.view.center.x+100, self.view.center.y+100); view3.center = CGPointMake(self.view.center.x+10, self.view.center.y+10); view1.hidden = NO; } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ // 把之前的动力效果移除 [dynamicAnimator removeAllBehaviors]; //在View1上添加重力效果 UIGravityBehavior * gravity = [[UIGravityBehavior alloc]initWithItems:@[view1]]; // 设置加速度 gravity.magnitude = 100; //设置动力效果的方向 gravity.gravityDirection = CGVectorMake(0, 1); // 添加到效果器 开始动力效果 [dynamicAnimator addBehavior:gravity]; UICollisionBehavior * collision = [[UICollisionBehavior alloc]initWithItems:@[view1,view2,view3]]; collision.collisionDelegate = self; collision.translatesReferenceBoundsIntoBoundary = YES; // 如果设置了 两个元素之间相互碰撞 设置了边界 也就不起作用了 // collision.collisionMode = UICollisionBehaviorModeItems; [dynamicAnimator addBehavior:collision]; #pragma mark----------------动力元素效果---------------------------- //可以与其他的 动力效果 配合使用 UIDynamicItemBehavior * item = [[UIDynamicItemBehavior alloc]initWithItems:@[view2,view1,view3]]; // 设置元素的跳跃度 item.elasticity = 0.9; [dynamicAnimator addBehavior:item]; }
当然还可以设置边界,当只添加View1时
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ // 把之前的动力效果移除 [dynamicAnimator removeAllBehaviors]; //在View1上添加重力效果 UIGravityBehavior * gravity = [[UIGravityBehavior alloc]initWithItems:@[view1]]; // 设置加速度 gravity.magnitude = 100; //设置动力效果的方向 gravity.gravityDirection = CGVectorMake(0, 1); // 添加到效果器 开始动力效果 [dynamicAnimator addBehavior:gravity]; #pragma mark ------碰撞效果----------------------- UICollisionBehavior * collision = [[UICollisionBehavior alloc]initWithItems:@[view1,view2]]; collision.collisionDelegate = self; // 设置一条下斜线边界 // [collision addBoundaryWithIdentifier:@"line1" fromPoint:CGPointMake(0, 300) toPoint:CGPointMake(400, 600)]; //设置竖直线边界 // [collision addBoundaryWithIdentifier:@"line2" fromPoint:CGPointMake(300, 0) toPoint:CGPointMake(300, 600)]; // 通过贝瑟尔曲线 画一个圆 UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 200, 300, 300)]; [collision addBoundaryWithIdentifier:@"yuan" forPath:path]; //把动力效果器的范围当做边界 collision.translatesReferenceBoundsIntoBoundary = YES; [dynamicAnimator addBehavior:collision]; }