iOS UIKit动力学(三)碰撞(UICollisionBehavior)

iOS UIKit力学(一)基本介绍(目录)

构造

UICollisionBehavior * collisionBehavior = 
[[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View]];

设置碰撞边界

UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View]];
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[_animator addBehavior:collisionBehavior];

iOS UIKit动力学(三)碰撞(UICollisionBehavior)_第1张图片

这是将重力向量设置为 {1, 1}后, _dynamicItem1ViewReference 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];

iOS UIKit动力学(三)碰撞(UICollisionBehavior)_第2张图片

collisionMode属性为 UICollisionBehaviorModeItems时,碰撞只发生在元素与元素之间,即使将 translatesReferenceBoundsIntoBoundary属性设置为 YES也不会检测边界碰撞。

  • 边界碰撞
UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View,_dynamicItem2View]];
collisionBehavior.collisionMode = UICollisionBehaviorModeBoundaries;
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[_animator addBehavior:collisionBehavior];

iOS UIKit动力学(三)碰撞(UICollisionBehavior)_第3张图片

collisionMode属性为 UICollisionBehaviorModeBoundaries时,运动元素只检测是否与边界发生碰撞,而不会检测是否与其他元素进行碰撞。
这里我们将 translatesReferenceBoundsIntoBoundary设置为 YES,发现蓝球与 Reference View边界发生了碰撞。
如果 translatesReferenceBoundsIntoBoundaryNO又会怎样呢?
iOS UIKit动力学(三)碰撞(UICollisionBehavior)_第4张图片

可以看出蓝球并没有与边界发生碰撞,这并不是因为 collisionMode属性没有生效,而是因为当 translatesReferenceBoundsIntoBoundaryNO时,就没有需要检测碰撞的边界了,所以蓝球因没有边界的阻挡会一直运动下去。
所以 translatesReferenceBoundsIntoBoundary属性只负责碰撞边界的设置,并不会影响碰撞的类型。

  • 碰撞所有
UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[_dynamicItem1View,_dynamicItem2View]];
collisionBehavior.collisionMode = UICollisionBehaviorModeEverything;
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[_animator addBehavior:collisionBehavior];
iOS UIKit动力学(三)碰撞(UICollisionBehavior)_第5张图片

碰撞边界内边距

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边界的内边距的。

iOS UIKit动力学(三)碰撞(UICollisionBehavior)_第6张图片

通过效果可以看出,碰撞边界的上下左右分别向内收缩了 50像素的距离。这里的 translatesReferenceBoundsIntoBoundary属性被设置为 NO,但是碰撞边界依然是有的,也就是说 setTranslatesReferenceBoundsIntoBoundaryWithInsets:函数和 translatesReferenceBoundsIntoBoundary属性设置的边界是相互独立的,两者之间没有联系。

自定义碰撞边界

  • 通过添加贝塞尔曲线,添加碰撞边界
-(void)addBoundaryWithIdentifier:(id )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];

iOS UIKit动力学(三)碰撞(UICollisionBehavior)_第7张图片

有关UIBezierPath请看: UIBezierPath介绍

  • 通过添加由两点组成的线段,添加碰撞边界
-(void)addBoundaryWithIdentifier:(id )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];
iOS UIKit动力学(三)碰撞(UICollisionBehavior)_第8张图片

效果中的红色边界线实际是看不到的,这里是为了效果格外添加上的。

  • 自定义边界其他相关方法
// 根据获取指定已命名的碰撞边界的贝塞尔曲线
-(nullable UIBezierPath *)boundaryWithIdentifier:(id )identifier;
// 移除指定已命名的碰撞边界
-(void)removeBoundaryWithIdentifier:(id )identifier;
// 获得所有命名
@property (nullable, nonatomic, readonly, copy) NSArray> *boundaryIdentifiers;
// 移除所有添加的碰撞边界
-(void)removeAllBoundaries;

代理方法

@protocol UICollisionBehaviorDelegate 
@optional
// 当一个两个动态元素之间发生碰撞时调用
- (void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id )item1 withItem:(id )item2 atPoint:(CGPoint)p;
// 当一个两个动态元素之间碰撞结束时调用
- (void)collisionBehavior:(UICollisionBehavior *)behavior endedContactForItem:(id )item1 withItem:(id )item2;

// 当一个动态元素与边界发生碰撞时调用
- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id )item withBoundaryIdentifier:(nullable id )identifier atPoint:(CGPoint)p;
// 当一个动态元素与边界碰撞结束时调用
- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id )item withBoundaryIdentifier:(nullable id )identifier;
@end

版权声明:出自MajorLMJ技术博客的原创作品 ,转载时必须注明出处及相应链接!

你可能感兴趣的:(iOS UIKit动力学(三)碰撞(UICollisionBehavior))