当UIGravityBehavior处于活动状态时,UIDynamicAnimator拒绝达到平衡

Nai*_*ler 9 animation ios uidynamicbehavior uikit-dynamics

我正在研究可扩展托盘视图的代码,该视图使用UIDynamicAnimator来实现漂亮的扩展/合约动画.

为了实现逼真的加速度,我使用UIGravityBehavior托盘下降,直到托盘的"标签"碰到屏幕底部.

这很有效,但即使场景中的所有项目都停止移动,UIDynamicAnimatorDelegate dynamicAnimatorDidPause:也从不调用.这意味着动画师继续使用CPU周期为场景设置动画(委托已设置并触发UIDynamicAnimatorDelegate dynamicAnimatorDidPause:).

我尝试UIGravityBehavior从场景中移除,这确实导致动画师最终停止.我没有时间去除重力行为,因为我需要在一切停止移动后将其从场景中移除.

我知道引力是一个恒定的力,但我仍然认为一旦所有的速度都为0且加速度为0,它就会停止动画师.

这最后一个假设是假的吗?

有类似问题的人吗?

Rob*_*ier 6

一旦所有东西都休息,动画师应该暂停是对的.

检查items重力行为的附加物,并确保没有其他物品掉落.例如,很容易意外地创建以下错误:

  • 添加重力和碰撞视图
  • 从superview和碰撞中删除视图
  • 无法从重力中删除视图

在这种情况下,"幽灵项目"将永远落下.

另一个可能的问题(虽然不太可能给出你的描述)是你的物品是否附加到导致无限但很小的"反弹"的其他行为上.我会检查你的动画师的完整行为列表(记得检查孩子的行为).特别是我对任何UIDynamicItemBehavior增加感兴趣elasticity.


编辑:

你可能也想走另一条路.从一个非常基本的动力学系统开始,添加您的组件,直到您可以重现问题.例如,以下会很快收敛(记录"暂停"):

@interface PTLViewController () <UIDynamicAnimatorDelegate>
@property (nonatomic, strong) UIDynamicAnimator *animator;
@end

@implementation PTLViewController

- (void)viewDidLoad {
  [super viewDidLoad];

  UIView *view = [[UIView alloc] initWithFrame:CGRectMake(100,100,100,100)];
  view.backgroundColor = [UIColor lightGrayColor];
  [self.view addSubview:view];

  self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
  self.animator.delegate = self;

  UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc] initWithItems:@[view]];
  collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
  [self.animator addBehavior:collisionBehavior];

  UIGravityBehavior *gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[view]];
  [self.animator addBehavior:gravityBehavior];
}

- (void)dynamicAnimatorDidPause:(UIDynamicAnimator *)animator {
  NSLog(@"pause");
}
@end
Run Code Online (Sandbox Code Playgroud)

关于获得所有项目速度的问题,我不知道一个简单的方法.不幸的是,UIDynamicAnimator并不直接知道它的所有项目.这是间接的,因为UIDyanamicBehavior不包括items属性.如果这对你造成的困扰,请考虑重复雷达:// 15054405.

但是如果您只想知道特定项目的当前线速度,则有一个解决方案.只需添加一个UIDynamicItemBehavior自定义操作即可记录它:

UIDynamicItemBehavior *dynamicItemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[view]];
__weak UIDynamicItemBehavior *weakBehavior = dynamicItemBehavior;
dynamicItemBehavior.action = ^{
  NSLog(@"Velocity: %@", NSStringFromCGPoint([weakBehavior linearVelocityForItem:view]));
};
[self.animator addBehavior:dynamicItemBehavior];
Run Code Online (Sandbox Code Playgroud)