首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >UIDynamicAnimator拒绝在UIGravityBehavior处于活动状态时达到平衡

UIDynamicAnimator拒绝在UIGravityBehavior处于活动状态时达到平衡
EN

Stack Overflow用户
提问于 2013-10-15 15:20:48
回答 3查看 5K关注 0票数 9

我正在为一个可扩展托盘视图编写代码,该视图使用UIDynamicAnimator来实现良好的展开/收缩动画。

为了达到一个真实的加速,我使用UIGravityBehavior使我的托盘下降,直到托盘的“选项卡”击中屏幕底部。

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

我试着将UIGravityBehavior从场景中移除,这确实导致动画师在最后停下来。我不能及时移除重力的行为,因为我需要把它从场景中移除,一旦一切停止移动。

我明白重力是一种恒定的力,但我仍然认为一旦所有物体都有0的速度和加速度,它就会阻止动画师。

最后一个假设是假的吗?

有类似的问题吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-10-15 16:16:42

你是正确的,动画师应该暂停,一旦一切恢复正常。

检查items与你的重力行为有什么联系,并确保没有其他项目仍在下降。例如,很容易意外地创建以下bug:

  • 添加引力和碰撞视图
  • 从超级视图和冲突中删除视图
  • 未能将视图从重力中移除

在这种情况下,“鬼项目”将永远倒下。

另一个可能的问题(虽然不太可能给出你的描述)是,如果你的项目被附加到其他行为,导致无限但小的“反弹”。我会检查动画师的全部行为列表(记住也要检查孩子的行为)。特别是,我对任何添加UIDynamicItemBehaviorelasticity都感兴趣。

编辑:

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

代码语言:javascript
复制
@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

对于你关于获得所有项目速度的问题,我不知道一个简单的方法。不幸的是,UIDynamicAnimator并不直接知道它的所有项目。这是间接的,因为UIDyanamicBehavior不包括items属性。如果这对你和我一样困扰,那就考虑一下欺骗radar://15054405吧。

但是有一个解决方案,如果你只想知道特定项目的当前线性速度。只需添加一个带有自定义操作的UIDynamicItemBehavior来记录它:

代码语言:javascript
复制
UIDynamicItemBehavior *dynamicItemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[view]];
__weak UIDynamicItemBehavior *weakBehavior = dynamicItemBehavior;
dynamicItemBehavior.action = ^{
  NSLog(@"Velocity: %@", NSStringFromCGPoint([weakBehavior linearVelocityForItem:view]));
};
[self.animator addBehavior:dynamicItemBehavior];
票数 6
EN

Stack Overflow用户

发布于 2013-10-15 15:51:10

我最近也遇到了类似的问题。最后,我使用了带边界的UICollisionBehavior,而不是条目(因为否则移动的项目会碰到其他的.)并实现委托方法collisionBehavior:beganContactForItem:withBoundaryIdentifier:atPoint:,以了解何时应该移除重力

代码语言:javascript
复制
UICollisionBehavior *collide = [[[UICollisionBehavior alloc] initWithItems:borders] retain];
[collide addItem:movingItem];

[collide setCollisionMode:UICollisionBehaviorModeBoundaries];
[collide setTranslatesReferenceBoundsIntoBoundary:YES];

如果您找到了更好的解决方案,请告诉我:)!

票数 1
EN

Stack Overflow用户

发布于 2015-05-13 17:09:58

我的问题是一样的。我的动画从未有过休息,所以一旦启动,我的应用程序将永远消耗3%到4%的CPU。我的视图似乎都在1/2秒钟内停止移动。所以,我没有弄清楚为什么我没有达到平衡,我只是用锤子敲击它,然后用计时器杀死动画师。我给它2秒。

代码语言:javascript
复制
- (void)createAnimator {
    if (_timer) {
        [_timer invalidate];
    }

    if (_animator) {
        [_animator removeAllBehaviors];
    }

    _animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

    // create all behaviors

    // kill the animator in 2 seconds
    _timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(killAnimator:) userInfo:nil repeats:NO];
}

- (void)killAnimator:(NSTimer *)timer {
    [_animator removeAllBehaviors];
    _animator = nil;
    _timer = nil;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19385003

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档