如何创建一个UIView弹跳动画?

102

我有一个作用于UIView finalScoreView 的CATransition,它使得它从屏幕顶部进入:

CATransition *animation = [CATransition animation];
animation.duration = 0.2;
animation.type = kCATransitionPush;
animation.subtype = kCATransitionFromBottom;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];

[gameOver.layer addAnimation:animation forKey:@"changeTextTransition"];
[finalScoreView.layer addAnimation:animation forKey:@"changeTextTransition"];

如何使得物体从上方进入屏幕后,落下一次弹跳停留不动?

非常感谢您的任何帮助!


3
你的目标是面向 iOS7 及以上版本吗?如果是,你可以利用 UIKit Dynamics。 - WDUK
4个回答

273

iOS 7中比UIDynamicAnimator更简单的选择是Spring Animation(一种新而强大的UIView块动画),它可以通过阻尼和速度产生漂亮的弹跳效果: Objective C

[UIView animateWithDuration:duration
  delay:delay
  usingSpringWithDamping:damping
  initialSpringVelocity:velocity
  options:options animations:^{
    //Animations
    }
  completion:^(BOOL finished) {
    //Completion Block
}];

Swift

UIView.animateWithDuration(duration,
     delay: delay,
     usingSpringWithDamping: damping,
     initialSpringVelocity: velocity,
     options: options,
     animations: {
            //Do all animations here
            }, completion: {
            //Code to run after animating
                (value: Bool) in
        })

Swift 4.0

UIView.animate(withDuration:duration,
     delay: delay,
     usingSpringWithDamping: damping,
     initialSpringVelocity: velocity,
     options: options,
     animations: {
            //Do all animations here
            }, completion: {
            //Code to run after animating
                (value: Bool) in
        })

usingSpringWithDamping 0.0表示弹性非常强,1.0表示平滑减速且不会超调。

initialSpringVelocity 大致上等于“期望距离除以期望时间”,其中1.0对应于在一秒钟内穿过总动画距离。例如,总动画距离为200个点,您希望动画的开始匹配100pt/s的视图速度,则使用0.5的值。

更详细的教程和示例应用程序可以在此教程中找到。我希望这对某些人有所帮助。


3
这是我创建的一个演示项目,旨在帮助您完美实现动画效果。请享用!https://github.com/jstnheo/SpringDampingDemo - jstn
谢谢你提供的演示项目,伙计。这真的有助于弄清楚这些值,因为它们相当晦涩。我希望苹果能够更清晰地表达它们。 - kakubei
我唯一的问题是它会超过我想要的点,至少在我动画化高度时是这样。 - 12944qwerty

147

使用iOS7和UIKit Dynamics,不再需要使用CAKeyframeAnimationsUIView动画!

看看苹果的UIKit Dynamics Catalog应用程序。或者,Teehanlax有一个明确、简洁的教程,其中包含完整的GitHub项目。如果您想了解动力学的内部细节,请查看Ray Winderlich教程。一如既往,首选参考文献是苹果文档,因此请查看文档中的UIDynamicAnimator类引用

这是来自Teenhanlax教程的代码片段:

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

UIGravityBehavior *gravityBehavior = 
                [[UIGravityBehavior alloc] initWithItems:@[self.redSquare]];
[self.animator addBehavior:gravityBehavior];
    
UICollisionBehavior *collisionBehavior = 
                [[UICollisionBehavior alloc] initWithItems:@[self.redSquare]]; 
collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
[self.animator addBehavior:collisionBehavior];
    
UIDynamicItemBehavior *elasticityBehavior = 
                [[UIDynamicItemBehavior alloc] initWithItems:@[self.redSquare]];
elasticityBehavior.elasticity = 0.7f;
[self.animator addBehavior:elasticityBehavior];

以下是结果

方形弹跳

UIKit Dynamics是iOS7中非常强大且易于使用的功能,可以创建出非常漂亮的UI。

其他示例:

按钮弹跳

滑动弹跳

弹性集合

WWDC春季集合

实现UIKit Dynamics的步骤始终相同:

  1. 创建一个UIDynamicAnimator对象并将其存储在强引用属性中
  2. 创建一个或多个UIDynamicBehaviors对象。每个行为应具有一个或多个项目,通常是要进行动画处理的视图。
  3. 确保UIDynamicBehaviors中使用的项目的初始状态是UIDynamicAnimator模拟中的有效状态。

1
嗨Michael,非常感谢你的帮助!这个看起来确实非常容易做到!我尝试了一下,当它触底时确实有效,但是与另一个视图不兼容 - https://dev59.com/DHzaa4cB1Zd3GeqPTbWj - 我希望你可以在这个问题上帮助我!:) 谢谢 - WunDaii
2
一个非常棒的教程,但你只需要使用一行代码,使用SpringWithDamping来实现弹跳效果! - Fattie
3
你能分享一些关于Uitableview弹跳动画的代码示例吗?我正在尝试使用UITableview,但不确定从哪里开始。 - Dinesh
1
UIKit Dynamics 在处理示例案例时非常好用。但是当涉及到真正的任务时,你会发现它是多么原始和受限制的。一个大问题是覆盖 UIDynamicItemBehavior(实际上是属性而不是行为)。你不能在不同的行为中使用不同的物理属性。另一个情况是实现类似于 UIScrollView 的橡胶边界 - 这非常复杂。我可以写更多,但评论太短了。 - kelin
2
请添加完整的代码。您的代码描述了如何创建UIDynamicAnimator及其相关对象,但没有回答如何使用它们。 - Vyachaslav Gerchicov
是的,我并不觉得这个答案有帮助,因为它过于探索性了,没有重点解决如何给UIView添加反弹的具体问题。我对于发掘可以做什么并不感兴趣,而更想知道如何解决特定的问题。 - Erika Electra

35

这里有一个演示项目,可帮助您达到完美的动画效果。请享用!

SpringDampingDemo

输入图像描述


谢谢你提供的演示项目,伙计。这真的有助于弄清楚这些值,因为它们相当晦涩。我希望苹果能让它们更清晰易懂。 - kakubei

-1
- (IBAction)searchViewAction:(UIButton*)sender
{
  if(sender.tag == 0)
  {
    sender.tag = 1;

    CGRect optionsFrame2 = self.defaultTopView.frame;
    optionsFrame2.origin.x = -320;

    CGRect optionsFrame = self.searhTopView.frame;
    optionsFrame.origin.x = 320;
    self.searhTopView.frame = optionsFrame;

    [UIView animateWithDuration:1.0 delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:1.0 options:0 animations:^{

        CGRect optionsFrame = self.searhTopView.frame;

        optionsFrame.origin.x = 0;
        self.searhTopView.frame = optionsFrame;
        self.defaultTopView.frame = optionsFrame2;
    } completion:^(BOOL finished) {
    }];        
}
else
{
    sender.tag = 0;

    CGRect optionsFrame2 = self.defaultTopView.frame;
    optionsFrame2.origin.x = 0;

    CGRect optionsFrame = self.searhTopView.frame;
    optionsFrame.origin.x = 320;

    [UIView animateWithDuration:1.0 delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:1.0 options:0 animations:^{

        CGRect optionsFrame = self.searhTopView.frame;

        optionsFrame.origin.x = 320;
        self.searhTopView.frame = optionsFrame;
        self.defaultTopView.frame = optionsFrame2;
    } completion:^(BOOL finished) {
    }];
}
}

1
代码中没有任何解释和注释,这并不有帮助。 - Lorenzo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接