我试图围绕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];
任何想法,即使快速按下,我怎么能让这两个动画进行排序而不会互相打断?
答案 0 :(得分:0)
这是一个潜在的行动计划。保留两个全局变量BOOL buttonPressed
和NSDate *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];