UIDynamic

简介

UIDynamiciOS 7之后新添加的一些物理仿真动画库,包含在UIKit框架中。

UIDynamic中的三个重要概念:
  • UIDynamicAnimator
    动画引擎。为动力学元素提供物理学相关的能力及动画,同时为这些元素提供相关的上下文,是动力学元素与底层iOS物理引擎之间的中介。
  • UIDynamicBehavior
    仿真行为。创建时,需要附带动画将要作用的视图。
  • UIDynamicItem
    动力学元素。从iOS7开始,UIViewUICollectionViewLayoutAttributes默认实现协议,如果自定义对象实现了该协议,即可通过Dynamic Animator实现物理仿真。

UIDynamicAnimator

  • 创建
    - (instancetype)initWithReferenceView:(UIView *)view;
    
    view参数:是一个参照视图,表示物理仿真的范围。
  • 添加一个物理仿真行为
    - (void)addBehavior:(UIDynamicBehavior *)behavior;
    
  • 移除一个物理仿真行为
    - (void)removeBehavior:(UIDynamicBehavior *)behavior;
    
  • 移除之前添加过的所有物理仿真行为
    - (void)removeAllBehaviors;
    
  • 更新我们已经修改的动态项目
    - (void)updateItemUsingCurrentState:(id <UIDynamicItem>)item;
    
  • 参照视图
    @property (nonatomic, readonly) UIView* referenceView;
    
  • 添加到物理仿真器中的所有物理仿真行为
    @property (nonatomic, readonly, copy) NSArray* behaviors;
    
  • 是否正在进行物理仿真
    @property (nonatomic, readonly, getter = isRunning) BOOL running;
    
  • 代理对象(能监听物理仿真器的仿真过程,比如开始和结束)
    @property (nonatomic, assign) id <UIDynamicAnimatorDelegate> delegate;
    
    @optional
    // 当dynamicAnimator将要恢复调用
    -(void)dynamicAnimatorWillResume:(UIDynamicAnimator *)animator;
    // 当dynamicAnimator已经暂停调用
    -(void)dynamicAnimatorDidPause:(UIDynamicAnimator *)animator;
    

UIDynamicItem

  • 中心
    @property (nonatomic, readwrite) CGPoint center;
    
  • 实时范围
    @property (nonatomic, readonly) CGRect bounds;
    
  • 旋转状态
    @property (nonatomic, readwrite) CGAffineTransform transform;
    

UIDynamicBehavior

在通常情况下我们不会直接使用UIDynamicBehavior类,而是使用它的子类们。在开始介绍它的子类前,先来看看UIDynamicBehavior作为父类的一些属性和方法:

  • 添加一个自定义行为子类
    - (void)addChildBehavior:(UIDynamicBehavior *)behavior;
    
  • 移除一个自定义行为子类
    - (void)removeChildBehavior:(UIDynamicBehavior *)behavior;
    
  • 当一个动态行为被添加或移除,会回调该函数
    - (void)willMoveToAnimator:(nullable UIDynamicAnimator *)dynamicAnimator;
    
  • 子行为 (只读)
    @property (nonatomic, readonly, copy) NSArray<__kindof UIDynamicBehavior *> *childBehaviors;
    
  • 在运行时调用的每一个动画步骤的block形式动作代码
    @property (nullable, nonatomic,copy) void (^action)(void);
    
  • 所属的dynamicAnimator
    @property (nullable, nonatomic, readonly) UIDynamicAnimator *dynamicAnimator;
    
1. UIGravityBehavior(重力行为)
  • 构造
    // 根据动力元素组构造
    - (instancetype)initWithItems:(NSArray<id <UIDynamicItem>> *)items;
    
    // 添加动力元素
    - (void)addItem:(id <UIDynamicItem>)item;
    // 删除动力元素
    - (void)removeItem:(id <UIDynamicItem>)item;
    // 获取说有动力元素
    @property (nonatomic, readonly, copy) NSArray<id <UIDynamicItem>> *items;
    
  • 重力方向
    // 这是二维坐标系中的方向,默认是(0.0, 1.0),表示垂直向下,数值越大;数值可以为负,如(0.0, -1.0)就表示重力方向是垂直向上。也可以利用x和y来表示二维坐标系中的任意方向。例如(1.0, 1.0)沿右下角45度方向,(1.0, 100000)极度接近竖直向下方向。
    @property (readwrite, nonatomic) CGVector gravityDirection;
    
  • 重力角度
    // 是一个角度,x轴正方向为0°,顺时针正数,逆时针负数)。
    @property (readwrite, nonatomic) CGFloat angle;
    
  • 力的系数
    // 正数时,沿`gravityDirection`方向,数值越大,加速度越大;负数时,`gravityDirection`的反方向,数值越小,加速度越大。
    @property (readwrite, nonatomic) CGFloat magnitude;
    

实例

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(0, 1);
//gravity.angle = M_PI*0.01;    
[self.animator addBehavior:gravity];

效果:
2. UICollisionBehavior (碰撞行为)
  • 构造
    // 根据动力元素组构造
    - (instancetype)initWithItems:(NSArray<id <UIDynamicItem>> *)items
    
    // 添加动力元素
    - (void)addItem:(id <UIDynamicItem>)item;
    // 删除动力元素
    - (void)removeItem:(id <UIDynamicItem>)item;
    // 获取所有动力元素
    @property (nonatomic, readonly, copy) NSArray<id <UIDynamicItem>> *items;
    
  • 碰撞模式
    @property (nonatomic, readwrite) UICollisionBehaviorMode collisionMode;
    
    typedef NS_OPTIONS(NSUInteger, UICollisionBehaviorMode) {
      UICollisionBehaviorModeItems        = 1 << 0, 元素碰撞
      UICollisionBehaviorModeBoundaries   = 1 << 1, 边界碰撞
      UICollisionBehaviorModeEverything   = NSUIntegerMax 全体碰撞
    } NS_ENUM_AVAILABLE_IOS(7_0);
    
  • 碰撞边界
    // 是否检测碰撞的边界
    @property (nonatomic, readwrite) BOOL translatesReferenceBoundsIntoBoundary;
    // 设置碰撞`ReferenceView`边界的内边距
    - (void)setTranslatesReferenceBoundsIntoBoundaryWithInsets:(UIEdgeInsets)insets;
    
    // 通过添加贝塞尔曲线,添加碰撞边界
    - (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier forPath:(UIBezierPath *)bezierPath;
    // 通过添加由两点组成的线段,添加碰撞边界
    - (void)addBoundaryWithIdentifier:(id <NSCopying>)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;
    
    // 根据获取指定已命名的碰撞边界的贝塞尔曲线
    - (nullable UIBezierPath *)boundaryWithIdentifier:(id <NSCopying>)identifier;
    // 移除指定已命名的碰撞边界
    - (void)removeBoundaryWithIdentifier:(id <NSCopying>)identifier;
    // 获得所有命名
    @property (nullable, nonatomic, readonly, copy) NSArray<id <NSCopying>> *boundaryIdentifiers;
    // 移除所有添加的碰撞边界
    - (void)removeAllBoundaries;
    
  • 代理
    // 碰撞代理
    @property (nullable, nonatomic, weak, readwrite) id <UICollisionBehaviorDelegate> collisionDelegate;
    
    @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;
    

实例一: 元素之间的碰撞

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(1, 1);
[self.animator addBehavior:gravity];
    
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView, self.blueView]];
collision.collisionMode = UICollisionBehaviorModeItems;
collision.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:collision];

效果:

实例二: 边界碰撞

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(1, 1);
[self.animator addBehavior:gravity];
    
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView, self.blueView]];
collision.collisionMode = UICollisionBehaviorModeBoundaries;
collision.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:collision];

效果:

实例三: 碰撞所有

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(1, 1);
[self.animator addBehavior:gravity];
    
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView, self.blueView]];
collision.collisionMode = UICollisionBehaviorModeEverything;
collision.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:collision];

效果:

实例四: 碰撞边界内边距

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(1, 1);
[self.animator addBehavior:gravity];
    
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView, self.blueView]];
collision.collisionMode = UICollisionBehaviorModeEverything;
[collision setTranslatesReferenceBoundsIntoBoundaryWithInsets:UIEdgeInsetsMake(50, 50, 50, 50)];
// 检测边距和内边距互相冲突,以最后设置为准
// collision.translatesReferenceBoundsIntoBoundary = NO;
[self.animator addBehavior:collision];

效果:

实例五: 贝塞尔曲线边界

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(1, 1);
[self.animator addBehavior:gravity];
    
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView]];
collision.collisionMode = UICollisionBehaviorModeEverything;
    
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 70, 200, 400)];
[collision addBoundaryWithIdentifier:@"path" forPath:path];
[self.animator addBehavior:collision];

效果:

实例六: 两点组成的线段边界

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(1, 1);
[self.animator addBehavior:gravity];
    
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView]];
collision.collisionMode = UICollisionBehaviorModeEverything;
    
[collision addBoundaryWithIdentifier:@"line" fromPoint:CGPointMake(200, 100) toPoint:CGPointMake(50, 400)];
[self.animator addBehavior:collision];

效果:
3. UIAttachmentBehavior (附着行为)

附着行为一般都是添加手势,让视图跟着手势移动,因为一般都是与手势搭配使用。

  • 构造
    // 元素和锚点之间的吸附
    - (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)point;
    // 元素和锚点之间的吸附,offset参数设置元素吸附力作用点的偏移量
    - (instancetype)initWithItem:(id <UIDynamicItem>)item offsetFromCenter:(UIOffset)offset attachedToAnchor:(CGPoint)point NS_DESIGNATED_INITIALIZER;
    
    // 元素和元素之间的吸附 
    - (instancetype)initWithItem:(id <UIDynamicItem>)item1 attachedToItem:(id <UIDynamicItem>)item2;
    // 元素和元素之间的吸附,offset1、offset2分别是两个元素吸附力作用点的偏移量
    - (instancetype)initWithItem:(id <UIDynamicItem>)item1 offsetFromCenter:(UIOffset)offset1 attachedToItem:(id <UIDynamicItem>)item2 offsetFromCenter:(UIOffset)offset2 NS_DESIGNATED_INITIALIZER;
    
  • 锚点
    当吸附发生在元素和锚点之间的时候,我们可以通过anchorPoint属性获得锚点位置,如果吸附发生在元素和元素之间的时候,该属性的值为(0, 0)。
    @property (readwrite, nonatomic) CGPoint anchorPoint;
    
  • 元素吸附力作用点和锚点的距离
    @property (readwrite, nonatomic) CGFloat length;
    
  • 振动频率
    除了刚性吸附之外弹性吸附也是很常用的类型,frequency属性就对弹性吸附有着直接的影响。
    // 值越大,弹性运动的频率越快。
    @property (readwrite, nonatomic) CGFloat frequency;
    
  • 弹性阻力
    属性是设置元素在弹性吸附时震动所受到的阻力,值越大,阻力越大,弹性运动震动的幅度越小。
    @property (readwrite, nonatomic) CGFloat damping;
    
  • 旋转阻力
    旋转力矩,指围绕一点旋转所受的阻力,默认值0.0,值越大,阻力越大。
    @property (readwrite, nonatomic) CGFloat frictionTorque NS_AVAILABLE_IOS(9_0);
    
  • 运动范围
    @property (readwrite, nonatomic) UIFloatRange attachmentRange NS_AVAILABLE_IOS(9_0);
    

实例一: 元素和锚点

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(1.0f, 1.0f);
[self.animator addBehavior:gravity];
    
UIAttachmentBehavior *attachment = [[UIAttachmentBehavior alloc] initWithItem:self.redView attachedToAnchor:CGPointMake(200, 300)];
attachment.length = 50;
[self.animator addBehavior:attachment];

效果:

实例二: 元素和锚点加偏移

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(1.0f, 1.0f);
[self.animator addBehavior:gravity];
    
UIAttachmentBehavior *attachment = [[UIAttachmentBehavior alloc] initWithItem:self.redView offsetFromCenter:UIOffsetMake(25, 0) attachedToAnchor:CGPointMake(200, 300)];
attachment.length = 50;
[self.animator addBehavior:attachment];

效果:

实例三: 元素与元素

UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
gravity.gravityDirection = CGVectorMake(0, 1.0f);
[self.animator addBehavior:gravity];
    
UIAttachmentBehavior *attachment = [[UIAttachmentBehavior alloc] initWithItem:self.redView attachedToItem:self.blueView];
attachment.length = 100;
[self.animator addBehavior:attachment];

效果:

实例四: 手势依附

// 添加手势
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] init];
[pan addTarget:self action:@selector(panDidHandler:)];
[self.view addGestureRecognizer:pan];

// 手势响应
- (void)panDidHandler:(UIPanGestureRecognizer *)pan {
    CGPoint location = [pan locationInView:self.view];
    if (pan.state == UIGestureRecognizerStateBegan) {
        self.attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:self.redView attachedToAnchor:location];
        [self.animator addBehavior:self.attachmentBehavior];
    } else if (pan.state == UIGestureRecognizerStateChanged) {
        self.attachmentBehavior.anchorPoint = location;
    } else if (pan.state == UIGestureRecognizerStateEnded) {
        [self.animator removeBehavior:self.attachmentBehavior];
    }
}

效果:
4. UIPushBehavior(推动行为)
  • 构造
    // 根据动力元素组和推动类型构造
    - (instancetype)initWithItems:(NSArray<id <UIDynamicItem>> *)items mode:(UIPushBehaviorMode)mode NS_DESIGNATED_INITIALIZER;
    
    typedef NS_ENUM(NSInteger, UIPushBehaviorMode) {
        UIPushBehaviorModeContinuous, // 连续的推动
        UIPushBehaviorModeInstantaneous // 瞬间的推动
    } NS_ENUM_AVAILABLE_IOS(7_0);
    
    // 添加动力元素
    - (void)addItem:(id <UIDynamicItem>)item;
    // 删除动力元素
    - (void)removeItem:(id <UIDynamicItem>)item;
    // 获取所有动力元素
    @property (nonatomic, readonly, copy) NSArray<id <UIDynamicItem>> *items;
    
  • 作用力中心偏移量
    - (UIOffset)targetOffsetFromCenterForItem:(id <UIDynamicItem>)item;
    - (void)setTargetOffsetFromCenter:(UIOffset)o forItem:(id <UIDynamicItem>)item;
    
  • 设置推力
    // 推力方向
    @property (readwrite, nonatomic) CGVector pushDirection;
    // 推力角度
    @property (readwrite, nonatomic) CGFloat angle;
    // 推力矢量的大小
    @property (readwrite, nonatomic) CGFloat magnitude;
    // 设置推力的角度和推力矢量的大小
    -(void)setAngle:(CGFloat)angle magnitude:(CGFloat)magnitude;
    
  • 推动行为是否处于活跃状态
    在添加一个pushBehavioranimator时,使用这个属性来激活或禁用推力作用,而不是通过重新添加behavior来实现。
    @property (nonatomic, readwrite) BOOL active;
    

实例一: 瞬间推动UIPushBehaviorModeInstantaneous

UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[self.redView] mode:UIPushBehaviorModeInstantaneous];
pushBehavior.pushDirection = CGVectorMake(0.5, 0.5);
[self.animator addBehavior:pushBehavior];
    
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView]];
collision.collisionMode = UICollisionBehaviorModeEverything;
collision.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:collision];

效果:


实例二: 连续推动UIPushBehaviorModeContinuous

UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[self.redView] mode:UIPushBehaviorModeContinuous];
pushBehavior.pushDirection = CGVectorMake(0.5, 0.5);
[self.animator addBehavior:pushBehavior];
    
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView]];
collision.collisionMode = UICollisionBehaviorModeEverything;
collision.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:collision];

效果:

实例三: 作用力中心偏移

UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[self.redView] mode:UIPushBehaviorModeInstantaneous];
pushBehavior.pushDirection = CGVectorMake(0.5, 0.5);
[pushBehavior setTargetOffsetFromCenter:UIOffsetMake(-25, 0) forItem:self.redView];
[self.animator addBehavior:pushBehavior];
    
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView]];
collision.collisionMode = UICollisionBehaviorModeEverything;
collision.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:collision];

效果:
5. UIDynamicItemBehavior (动力行为)

因为可以设置摩擦力、弹力、密度、阻力等参数,在模拟视图运动的能量损失。

  • 构造
    // 根据动力元素组构造
    - (instancetype)initWithItems:(NSArray<id <UIDynamicItem>> *)items NS_DESIGNATED_INITIALIZER;
    
    // 添加动力元素
    - (void)addItem:(id <UIDynamicItem>)item;
    // 删除动力元素
    - (void)removeItem:(id <UIDynamicItem>)item;
    // 获取所有动力元素
    @property (nonatomic, readonly, copy) NSArray<id <UIDynamicItem>> *items;
    
  • 弹性系数
    用于碰撞行为的动态元素的弹性量。默认0,范围0.0 ~ 1.0。
    @property (readwrite, nonatomic) CGFloat elasticity;
    
  • 摩擦系数
    用于两个发生摩擦的动态元素。默认值0.0(没有摩擦),当值为1.0时,强烈摩擦。如果设置更高的摩擦,可以使用更高的数值。
    @property (readwrite, nonatomic) CGFloat friction;
    
  • 相对质量密度
    用于动态元素相对密度。其连同动态元素大小,决定动态元素的有效质量。其参与的动力学行为包括摩擦、碰撞、推动等...默认1。
    @property (readwrite, nonatomic) CGFloat density;
    

    假设你有两个具有相同密度但大小不同的动态元素:元素一尺寸为100x100像素点,元素二尺寸为100x200像素点。
    这个例子中,元素二的有效质量是元素一的两倍。
    在一个弹性碰撞中,这些元素根据它们的相对质量表现出自然的动量守恒。元素一密度为1.0,当施加一个力(通过推动行为)1.0级时,加速度为100点/s²。

  • 线速度阻尼
    默认值是0.0。有效范围从0.0(没有速度阻尼)到CGFLOAT_MAX(最大速度阻尼)。当设置为1.0,动态元素会立马停止就像没有力量作用于它一样。
    @property (readwrite, nonatomic) CGFloat resistance;
    
  • 角速度阻尼
    有效范围从0.0到CGFLOAT_MAX,值越大,角速度阻尼越大,旋转减速越快,到停止。
    @property (readwrite, nonatomic) CGFloat angularResistance;
    
  • 电荷
    电荷数确定动态元素与电场和磁场相互作用的程度。这个属性值没有单位,电磁场强度由你调控的适当的值来决定。默认值0.0。
    @property (readwrite, nonatomic) CGFloat charge NS_AVAILABLE_IOS(9_0);
    
  • 是否固定
    当一个动态元素被设置为固定后,该元素参与碰撞,但不受碰撞影响,仿佛成为一个碰撞边界。默认值为NO。
    @property (nonatomic, getter = isAnchored) BOOL anchored NS_AVAILABLE_IOS(9_0);
    
  • 添加一个动态元素,并设置它的角速度
    默认值为0.0,单位弧度/秒。设置一个负值,减少一定角速度。
    -(void)addAngularVelocity:(CGFloat)velocity forItem:(id<UIDynamicItem>)item;
    
  • 添加一个动态元素,并设置它的线速度
    默认值为0.0,单位点/秒。设置一个负值,减少一定线速度。
    -(void)addLinearVelocity:(CGPoint)velocity forItem:(id<UIDynamicItem>)item;
    
  • 获得动态元素的角速度
    -(CGFloat)angularVelocityForItem:(id<UIDynamicItem>)item;
    
  • 获得动态元素的线速度
    -(CGPoint)linearVelocityForItem:(id<UIDynamicItem>)item;
    

实例:

- (void)addDynamicItem {
    UIDynamicItemBehavior *dynamicItem = [[UIDynamicItemBehavior alloc] initWithItems:@[self.redView]];
    dynamicItem.elasticity = 0.5f; // 弹性系数
    dynamicItem.friction = 1.0f; // 摩擦系数
    dynamicItem.density = 10.0f; // 相对质量密度
    dynamicItem.resistance = 10.0f; // 线性阻尼
    dynamicItem.angularResistance = 10.0f; // 角度阻尼
    [self.animator addBehavior:dynamicItem];
    
    // 推动行为
    UIPushBehavior *pushBehavior = [[UIPushBehavior alloc] initWithItems:@[self.redView] mode:UIPushBehaviorModeInstantaneous];
    pushBehavior.pushDirection = CGVectorMake(0.5, 0);
    pushBehavior.magnitude = 20;
    [pushBehavior setTargetOffsetFromCenter:UIOffsetMake(0, -25) forItem:self.redView];
    [self.animator addBehavior:pushBehavior];
    
    // 碰撞行为
    UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[self.redView]];
    collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
    [self.animator addBehavior:collisionBehavior];
}

效果:
6. UISnapBehavior (捕获行为)

捕获行为是定义一个动态元素运动到指定点,运动过程伴随弹簧效果。

  • 构造
    - (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point NS_DESIGNATED_INITIALIZER;
    
  • 捕获点
    该属性的默认值为initWithItem:snapToPoint:方法设置的值,当该属性的值发生改变时,捕获行为会更新,动态元素会向新的捕获点捕获。
    @property (nonatomic, assign) CGPoint snapPoint NS_AVAILABLE_IOS(9_0);
    
  • 震动阻尼
    阻尼的有效范围为0.0~1.0,0.0最大震荡、1.0最小震荡,默认值为0.5。
    @property (nonatomic, assign) CGFloat damping;
    

实例:

UISnapBehavior *snapBehavior = [[UISnapBehavior alloc] initWithItem:self.redView snapToPoint:CGPointMake(200, 300)];
snapBehavior.damping = 0.2f;
[self.animator addBehavior:snapBehavior];

效果:
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • 物理仿真器 UIDynamicAnimator的常见方法 -(void)addBehavior:(UIDynami...
    Hevin_Chen阅读 171评论 0 0
  • 简介 什么是UIDynamic UIDynamic是从iOS 7开始引入的一种新技术,隶属于UIKit框架 可以认...
    JonesCxy阅读 189评论 0 1
  • 本文中所有代码演示均有GitHub源码,点击下载 UIDynamic简介 简介:UIKit动力学最大的特点是将现实...
    si1ence阅读 10,191评论 8 79
  • UIDynamic 中的三个重要概念 •Dynamic Animator:动画者,为动力学元素提供物理学相关的能力...
    方圆十里不留母狗阅读 434评论 0 0
  • 我好像快要坚持不下去了,我想放弃的感觉,为什么自己连怎么一点小事都做不好,道理我都懂,可是做起来好难,不要逃避问题...
    guoguoguoguoguo阅读 184评论 0 0