1.5碰撞行为UICollisionBehavior
(一)碰撞行为UICollisionBehavior作用
作用:可以让物体之间实现碰撞效果,可以通过添加边界(boundary)将碰撞行为限定到某个区域.
(二)常用属性和方法
常用属性
@property (nonatomic, readonly, copy) NSArray<id <UIDynamicItem>> *items;
// 碰撞模式(有三种:元素碰撞,边界碰撞,全体碰撞)
// UICollisionBehaviorModeItems(元素碰撞),
// UICollisionBehaviorModeBoundaries(边界碰撞),
// UICollisionBehaviorModeEverything(全体碰撞).
@property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;
// 是否已参照视图的bounds为边界
@property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;
// 所有的碰撞边界
@property (nullable, nonatomic, readonly, copy) NSArray<id <NSCopying>> *boundaryIdentifiers;
// 代理对象,可以监听碰撞的过程
@property (nullable, nonatomic, weak, readwrite) id <UICollisionBehaviorDelegate> collisionDelegate;
常用方法
// 初始化一个碰撞行为,items:代表碰撞行为作用的所有仿真元素
- (instancetype)initWithItems:(NSArray<id <UIDynamicItem>> *)items;
// 添加一个仿真元素到碰撞行为
- (void)addItem:(id <UIDynamicItem>)item;
// 移除碰撞行为上的一个仿真元素
- (void)removeItem:(id <UIDynamicItem>)item;
// 设置碰撞行为参照视图的边界,并且设置内边距
- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;
// 添加一个路径作为碰撞行为的边界 identifier:边界ID bezierPath:使用UIBezierPath描述的一个边界
- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier forPath:(UIBezierPath *)bezierPath;
// 添加一个从p1到p2的边界 identifier:边界ID
- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;
// 根据指定ID返回一个使用UIBezierPath描述的路径
- (nullable UIBezierPath *)boundaryWithIdentifier:(id <NSCopying>)identifier;
// 移除碰撞行为上指定ID为identifier的边界
- (void)removeBoundaryWithIdentifier:(id <NSCopying>)identifier;
// 移除碰撞行为上的所有边界
- (void)removeAllBoundaries;
(三)UICollisionBehaviorDelegate
// 仿真元素和仿真元素碰撞开始 item1:仿真元素1 item2:仿真元素2 p:碰撞点
- (void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p;
// 仿真元素和仿真元素碰撞结束 item1:仿真元素1 item2:仿真元素2
- (void)collisionBehavior:(UICollisionBehavior *)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2;
// 仿真元素和边界碰撞开始 item:仿真元素 identifier:边界ID p:碰撞点
- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(nullable id <NSCopying>)identifier atPoint:(CGPoint)p;
// 仿真元素和边界碰撞结束 item:仿真元素 identifier:边界ID
- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(nullable id <NSCopying>)identifier;
示例代码:
// 控制器View
@interface RBView : UIView
@property (nonatomic, assign) CGRect rectR;
@end
@implementation RBView
- (void)drawRect:(CGRect)rect{
UIBezierPath *path = [[UIBezierPath alloc] init];
[path moveToPoint:CGPointMake(0, 300)];
[path addLineToPoint:CGPointMake(200, 350)];
[path stroke];
[[UIBezierPath bezierPathWithRect:self.rectR] stroke];
}
@end
@interface RView : UIView
@property (nonatomic, assign) CGRect rectR;
@end
@implementation RView
- (void)drawRect:(CGRect)rect{
[[UIBezierPath bezierPathWithRect:self.rectR] stroke];
}
@end
@interface ViewController ()<UICollisionBehaviorDelegate>
@property (nonatomic, weak) RView *redView;
@property (nonatomic, weak) UIView *blueView;
@property (nonatomic, strong) UIDynamicAnimator *animator;
@end
@implementation ViewController
- (void)loadView{
self.view = [[RBView alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.view.backgroundColor = [UIColor whiteColor];
}
- (void)viewDidLoad {
[super viewDidLoad];
RView *redView = [[RView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];
UIView *blueView = [[UIView alloc] initWithFrame:CGRectMake(180, [UIScreen mainScreen].bounds.size.height - 150, 50, 50)];
blueView.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView];
self.redView = redView;
self.blueView = blueView;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
// 1.创建仿真器
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
// 2.创建物理仿真行为
// 重力行为
UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
// 碰撞行为
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView,self.blueView]];
// 设置边界碰撞
collision.translatesReferenceBoundsIntoBoundary = YES;
// 碰撞的action属性 实时监听碰撞过程
collision.action = ^{
// 需要强转
RBView *rbView = (RBView *)self.view;
rbView.rectR = self.redView.frame;
[self.view setNeedsDisplay];
NSLog(@"%@", NSStringFromCGRect(self.redView.frame));
// 判断如果碰撞view的高大于105将颜色变成brownColor颜色 可以做一些加分什么的逻辑
if (self.redView.frame.size.height > 105) {
self.redView.backgroundColor = [UIColor brownColor];
}else{
self.redView.backgroundColor = [UIColor redColor];
}
};
// 碰撞的模式
collision.collisionMode = UICollisionBehaviorModeEverything;
CGPoint startp = CGPointMake(0, 300);
CGPoint endp = CGPointMake(200, 350);
// 使用两点创建碰撞边界
[collision addBoundaryWithIdentifier:@"key1" fromPoint:startp toPoint:endp];
// 使用UIBezierPath创建碰撞边界
UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.blueView.frame];
[collision addBoundaryWithIdentifier:@"key" forPath:path];
// 碰撞设置代理
collision.collisionDelegate = self;
// 3.将仿真行为添加到仿真器
[self.animator addBehavior:gravity];
[self.animator addBehavior:collision];
}
// 碰撞代理
- (void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id<UIDynamicItem>)item withBoundaryIdentifier:(id<NSCopying>)identifier atPoint:(CGPoint)p{
// 需要强制类型转化
NSString *key = (NSString *)identifier;
if ([key isEqualToString:@"key1"]) {
self.redView.backgroundColor = [UIColor yellowColor];
}else{
self.redView.backgroundColor = [UIColor redColor];
}
}
@end