构造
UICollisionBehavior * collisionBehavior =
[[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View]];
设置碰撞边界
UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View]];
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[_animator addBehavior:collisionBehavior];
这是将重力向量设置为
{1, 1}
后,_dynamicItem1View
与Reference View
边界碰撞产生的效果。translatesReferenceBoundsIntoBoundary
属性表示是否以当前坐标系边界作为检测碰撞的边界。此时_dynamicItem1View
运动到self.view
的边界时就会发生碰撞。
碰撞的类型
@property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;
typedef NS_OPTIONS(NSUInteger, UICollisionBehaviorMode) {
// 元素之间的碰撞
UICollisionBehaviorModeItems = 1 << 0,
// 边界碰撞
UICollisionBehaviorModeBoundaries = 1 << 1,
// 碰撞所有
UICollisionBehaviorModeEverything = NSUIntegerMax
} NS_ENUM_AVAILABLE_IOS(7_0);
- 元素之间的碰撞
UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View,_dynamicItem2View]];
collisionBehavior.collisionMode = UICollisionBehaviorModeItems;
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[_animator addBehavior:collisionBehavior];
当
collisionMode
属性为UICollisionBehaviorModeItems
时,碰撞只发生在元素与元素之间,即使将translatesReferenceBoundsIntoBoundary
属性设置为YES
也不会检测边界碰撞。
- 边界碰撞
UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View,_dynamicItem2View]];
collisionBehavior.collisionMode = UICollisionBehaviorModeBoundaries;
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[_animator addBehavior:collisionBehavior];
当
collisionMode
属性为UICollisionBehaviorModeBoundaries
时,运动元素只检测是否与边界发生碰撞,而不会检测是否与其他元素进行碰撞。这里我们将
translatesReferenceBoundsIntoBoundary
设置为YES
,发现蓝球与Reference View
边界发生了碰撞。如果
translatesReferenceBoundsIntoBoundary
为NO
又会怎样呢?可以看出蓝球并没有与边界发生碰撞,这并不是因为
collisionMode
属性没有生效,而是因为当translatesReferenceBoundsIntoBoundary
为NO
时,就没有需要检测碰撞的边界了,所以蓝球因没有边界的阻挡会一直运动下去。所以
translatesReferenceBoundsIntoBoundary
属性只负责碰撞边界的设置,并不会影响碰撞的类型。
- 碰撞所有
UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View,_dynamicItem2View]];
collisionBehavior.collisionMode = UICollisionBehaviorModeEverything;
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[_animator addBehavior:collisionBehavior];
碰撞边界内边距
UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View,_dynamicItem2View]];
collisionBehavior.collisionMode = UICollisionBehaviorModeEverything;
collisionBehavior.translatesReferenceBoundsIntoBoundary = NO;
[collisionBehavior setTranslatesReferenceBoundsIntoBoundaryWithInsets:UIEdgeInsetsMake(50, 50, 50, 50)];
[_animator addBehavior:collisionBehavior];
setTranslatesReferenceBoundsIntoBoundaryWithInsets:
函数是用来设置碰撞Reference View
边界的内边距的。
通过效果可以看出,碰撞边界的上下左右分别向内收缩了
50
像素的距离。这里的translatesReferenceBoundsIntoBoundary
属性被设置为NO
,但是碰撞边界依然是有的,也就是说setTranslatesReferenceBoundsIntoBoundaryWithInsets:
函数和translatesReferenceBoundsIntoBoundary
属性设置的边界是相互独立的,两者之间没有联系。
自定义碰撞边界
- 通过添加贝塞尔曲线,添加碰撞边界
-(void)addBoundaryWithIdentifier:(id <NSCopying>)identifier forPath:(UIBezierPath *)bezierPath;
// 创建椭圆形路径对象
UIBezierPath * path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 50, 200, 500)];
path.lineWidth = 1.f;
path.lineCapStyle = kCGLineCapRound;
path.lineJoinStyle = kCGLineCapRound;
UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View]];
collisionBehavior.collisionMode = UICollisionBehaviorModeEverything;
[collisionBehavior addBoundaryWithIdentifier:@"path1" forPath:path];
[_animator addBehavior:collisionBehavior];
有关UIBezierPath请看:UIBezierPath介绍
- 通过添加由两点组成的线段,添加碰撞边界
-(void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;
UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View]];
collisionBehavior.collisionMode = UICollisionBehaviorModeEverything;
[collisionBehavior addBoundaryWithIdentifier:@"path2" fromPoint:CGPointMake(350, 100) toPoint:CGPointMake(150, 500)];
[_animator addBehavior:collisionBehavior];
效果中的红色边界线实际是看不到的,这里是为了效果格外添加上的。
- 自定义边界其他相关方法
// 根据获取指定已命名的碰撞边界的贝塞尔曲线
-(nullable UIBezierPath *)boundaryWithIdentifier:(id <NSCopying>)identifier;
// 移除指定已命名的碰撞边界
-(void)removeBoundaryWithIdentifier:(id <NSCopying>)identifier;
// 获得所有命名
@property (nullable, nonatomic, readonly, copy) NSArray<id <NSCopying>> *boundaryIdentifiers;
// 移除所有添加的碰撞边界
-(void)removeAllBoundaries;
代理方法
@protocol UICollisionBehaviorDelegate <NSObject>
@optional
// 当一个两个动态元素之间发生碰撞时调用
- (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:(nullable id <NSCopying>)identifier atPoint:(CGPoint)p;
// 当一个动态元素与边界碰撞结束时调用
- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(nullable id <NSCopying>)identifier;
@end
版权声明:出自MajorLMJ技术博客的原创作品 ,转载时必须注明出处及相应链接!