协调UIButton上的两个UIView动画向下/向上

时间:2014-06-19 03:20:08

标签: ios objective-c animation uibutton

我试图围绕UIButton制作动画。 UIButton有一个UIImageView,它包含一个我想在UIButton被按下时收缩的图像,然后当UIButton被释放时,我想播放一个反弹的单独动画。 / p>

我现在遇到的问题是,如果我按下然后非常快速地按下动画,动画的第二部分似乎无法播放。如果我按住(等待第一个动画完成),然后放手,它似乎工作正常。

以下是相关代码:

-(void)pressedDown
{
[UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
                self.heartPart.layer.transform = CATransform3DMakeScale(0.8, 0.8, 1);
            } completion:nil];
}

-(void)pressedUp
{
[UIView animateWithDuration:0.8
                                      delay:0.0
                     usingSpringWithDamping:20
                      initialSpringVelocity:200
                                    options:UIViewAnimationOptionBeginFromCurrentState
                                 animations:^{
                                     self.heartPart.layer.transform = CATransform3DIdentity;
                                 }
                                 completion:nil];
            }];
}

在我的ViewDidLoad我添加以下内容:

[self.heartButton addTarget:self
                     action:@selector(pressedUp)
           forControlEvents:UIControlEventTouchUpInside];

[self.heartButton addTarget:self
                     action:@selector(PressedDown)
           forControlEvents:UIControlEventTouchDown];

任何想法,即使快速按下,我怎么能让这两个动画进行排序而不会互相打断?

3 个答案:

答案 0 :(得分:0)

这是一个潜在的行动计划。保留两个全局变量BOOL buttonPressedNSDate *buttonPressDate。按下按钮时,您应将buttonPressed设置为true并将buttonPressDate设置为当前日期。现在,在修饰方法中,您可以将buttonPressed设置为false,并检查buttonPressDate与当前日期之间的时间间隔是否大于动画的持续时间。如果是,则运行补足动画;如果没有,请返回。在触地下降方法的完成块中,您将检查按钮是否仍然按下。如果是,那就什么都不做;如果它不再按下,则运行补足动画。

使用此方法可以获得以下效果:如果您快速点击按钮,它将运行完整的0.2秒缩小动画,然后按顺序运行放大动画。

现在,如果您不希望在快速触摸的情况下运行降落动画,则应该延迟第一个动画并检查按钮在启动时是否仍然按下。如果是快速触摸,您将运行一个修改过的动画,其中包括触摸和触摸阶段。

答案 1 :(得分:0)

您可以尝试以下方法: -

 //Set only one target with TouchUpInside.
  [self.heartButton addTarget:self
                 action:@selector(pressedUp)
       forControlEvents:UIControlEventTouchUpInside];


-(void)pressedDown
{
  [UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
            self.heartPart.layer.transform = CATransform3DMakeScale(0.8, 0.8, 1);
        } 
    completion:

    [self pressedUp];
    //Or
    [self performSelector:@selector(pressedUp) withObject:self afterDelay:0.5]; 

  ];       
}

 -(void)pressedUp
 {
   [UIView animateWithDuration:0.8
                                  delay:0.0
                 usingSpringWithDamping:20
                  initialSpringVelocity:200
                                options:UIViewAnimationOptionBeginFromCurrentState
                             animations:^{
                                 self.heartPart.layer.transform = CATransform3DIdentity;
                             }
                             completion:nil];
        }];
 }

这样,当第一个动画完成后,下一个动画将开始但是我担心的是它看起来不合适,并且向用户展示它会有点长动画。把它放在你的应用程序设计上,以及它将用它实现的目标。

答案 2 :(得分:0)

我假设您熟悉操作的概念。如果没有,那么NSOperations允许您保持代码模块化并使您能够设置执行顺序。

您可以创建NSOperation的自定义子类并在其执行块中运行动画,然后在每次用户与按钮交互时在队列中添加带动画的操作。

除了documentation from Apple之外,还有一个很好的例子,说明如何在Github上提供NSOperation的子类:

https://github.com/robertmryan/AFHTTPSessionOperation/blob/master/Source/AsynchronousOperation.m

根据您的自定义操作的“蓝图”,实现您想要的目标非常简单,例如:

@interface PressDownAnimationOperation : AsynchronousOperation

- (instancetype)initWithView:(UIView *)view;

@end

@implementation PressDownAnimationOperation {
    UIView *_view;
}

- (instancetype)initWithView:(UIView *)view {
    self = [super init];
    if(self) {
        _view = view;
    }
    return self;
}

- (void)main {
    // dispatch UIKit related stuff on main thread
    dispatch_async(dispatch_get_main_queue(), ^{
        // animate
        [UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
                _view.layer.transform = CATransform3DMakeScale(0.8, 0.8, 1);
            } completion:^(BOOL finished){
              // mark operation as finished
              [self completeOperation];
            }];
    });
}

@end

现在,为了运行动画,您需要创建NSOperationQueue。您可以将它保存在视图控制器中,即:

@implementation ViewController {
    NSOperationQueue *_animationQueue;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    _animationQueue = [[NSOperationQueue alloc] init];

    // limit queue to run single operation at a time
    _animationQueue.maxOperationCount = 1;
}

@end

现在,当你想链接动画时,你只需创建新的操作,将它添加到队列即可,即:。

- (void)pressedDown {
    NSOperation *animationOperation = [[PressDownAnimationOperation alloc] init];

   [_animationQueue addOperation:animationOperation];
}

如果用户点击太快而你注意到你的操作队列被动画阻塞,你可以在添加新动画之前取消所有动画,即:

[_animationQueue cancelAllOperations];