1.5碰撞行為UICollisionBehavior
(一)碰撞行為UICollisionBehavior作用
作用:可以讓物體之間實(shí)現(xiàn)碰撞效果,可以通過(guò)添加邊界(boundary)將碰撞行為限定到某個(gè)區(qū)域.
(二)常用屬性和方法
常用屬性
@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;
// 代理對(duì)象,可以監(jiān)聽(tīng)碰撞的過(guò)程
@property (nullable, nonatomic, weak, readwrite) id <UICollisionBehaviorDelegate> collisionDelegate;
常用方法
// 初始化一個(gè)碰撞行為,items:代表碰撞行為作用的所有仿真元素
- (instancetype)initWithItems:(NSArray<id <UIDynamicItem>> *)items;
// 添加一個(gè)仿真元素到碰撞行為
- (void)addItem:(id <UIDynamicItem>)item;
// 移除碰撞行為上的一個(gè)仿真元素
- (void)removeItem:(id <UIDynamicItem>)item;
// 設(shè)置碰撞行為參照視圖的邊界,并且設(shè)置內(nèi)邊距
- (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;
// 添加一個(gè)路徑作為碰撞行為的邊界 identifier:邊界ID bezierPath:使用UIBezierPath描述的一個(gè)邊界
- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier forPath:(UIBezierPath *)bezierPath;
// 添加一個(gè)從p1到p2的邊界 identifier:邊界ID
- (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;
// 根據(jù)指定ID返回一個(gè)使用UIBezierPath描述的路徑
- (nullable UIBezierPath *)boundaryWithIdentifier:(id <NSCopying>)identifier;
// 移除碰撞行為上指定ID為identifier的邊界
- (void)removeBoundaryWithIdentifier:(id <NSCopying>)identifier;
// 移除碰撞行為上的所有邊界
- (void)removeAllBoundaries;
(三)UICollisionBehaviorDelegate
// 仿真元素和仿真元素碰撞開(kāi)始 item1:仿真元素1 item2:仿真元素2 p:碰撞點(diǎn)
- (void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2 atPoint:(CGPoint)p;
// 仿真元素和仿真元素碰撞結(jié)束 item1:仿真元素1 item2:仿真元素2
- (void)collisionBehavior:(UICollisionBehavior *)behavior endedContactForItem:(id <UIDynamicItem>)item1 withItem:(id <UIDynamicItem>)item2;
// 仿真元素和邊界碰撞開(kāi)始 item:仿真元素 identifier:邊界ID p:碰撞點(diǎn)
- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(nullable id <NSCopying>)identifier atPoint:(CGPoint)p;
// 仿真元素和邊界碰撞結(jié)束 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.創(chuàng)建仿真器
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
// 2.創(chuàng)建物理仿真行為
// 重力行為
UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
// 碰撞行為
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView,self.blueView]];
// 設(shè)置邊界碰撞
collision.translatesReferenceBoundsIntoBoundary = YES;
// 碰撞的action屬性 實(shí)時(shí)監(jiān)聽(tīng)碰撞過(guò)程
collision.action = ^{
// 需要強(qiáng)轉(zhuǎn)
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);
// 使用兩點(diǎn)創(chuàng)建碰撞邊界
[collision addBoundaryWithIdentifier:@"key1" fromPoint:startp toPoint:endp];
// 使用UIBezierPath創(chuàng)建碰撞邊界
UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.blueView.frame];
[collision addBoundaryWithIdentifier:@"key" forPath:path];
// 碰撞設(shè)置代理
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{
// 需要強(qiáng)制類型轉(zhuǎn)化
NSString *key = (NSString *)identifier;
if ([key isEqualToString:@"key1"]) {
self.redView.backgroundColor = [UIColor yellowColor];
}else{
self.redView.backgroundColor = [UIColor redColor];
}
}
@end