I'm making a simple UIButton subclass that "pulses" by changing the alpha using UIView animations. The problem I'm having is setting the alpha to 1 (100%) when the user touches down on the button. I have code to pause and resume the animation but setting the opacity before or after the call to pauseAnimations does not seem to work.
Pausing/Resuming animations on the UIView's layer:
-(void)pauseAnimation {
CFTimeInterval pausedTime = [self convertTime:CACurrentMediaTime()
fromLayer:nil];
self.speed = 0.0;
self.timeOffset = pausedTime;
}
-(void)resumeAnimation {
CFTimeInterval pausedTime = [self timeOffset];
self.speed = 1.0;
self.timeOffset = 0.0;
self.beginTime = 0.0;
CFTimeInterval timeSincePause = [self convertTime:CACurrentMediaTime()
fromLayer:nil] - pausedTime;
self.beginTime = timeSincePause;
}
Code for the UIButton subclass:
-(id)initWithAnimationInterval:(NSTimeInterval)interval andMinimumAlpha:
(float)minimumAlpha andMaximumAlpha:(float)maximumAlpha {
if ((self = [super init])) {
_animationInterval = interval;
_minimumAlpha = minimumAlpha;
_maximumAlpha = maximumAlpha;
self.alpha = self.minimumAlpha;
[self addTarget:self action:@selector(buttonDown)
forControlEvents:UIControlEventTouchDown];
[self addTarget:self action:@selector(buttonUp)
forControlEvents:UIControlEventTouchUpInside];
[self addTarget:self action:@selector(buttonUp)
forControlEvents:UIControlEventTouchUpOutside];
[self startAnimating];
}
return self;
}
-(void)startAnimating {
[UIView animateWithDuration:self.animationInterval
delay:0
options:UIViewAnimationOptionAllowAnimatedContent |
UIViewAnimationOptionAllowUserInteraction |
UIViewAnimationOptionAutoreverse |
UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionRepeat
animations:^{
self.alpha = self.maximumAlpha;
}
completion:^(BOOL finished) {
}];
}
-(void)buttonDown {
[self.layer pauseAnimation];开发者_如何学Python
self.oldAlpha = self.alpha;
self.alpha = self.maximumAlpha;
}
-(void)buttonUp {
self.alpha = self.oldAlpha;
[self.layer resumeAnimation];
}
Try removing UIViewAnimationOptionRepeat from the animation options. If you use it there it means that the animation will be repeated indefinitely. So it does not help to stop the timer because the animation will keep on repeating.
Have you thought about using NSTimer? It seems to an easier approach. Here's what I did:
- (void)viewDidLoad
{
[super viewDidLoad];
[button addTarget:self action:@selector(buttonDown) forControlEvents:UIControlEventTouchDown];
[button addTarget:self action:@selector(buttonUp) forControlEvents:UIControlEventTouchUpInside];
[button addTarget:self action:@selector(buttonUp) forControlEvents:UIControlEventTouchUpOutside];
[self startTimer];
}
- (void)startTimer {
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.4 target:self selector:@selector(timerFired:) userInfo:nil repeats:YES];
}
- (void)stopTimer {
[timer invalidate];
}
- (void)buttonDown {
[self stopTimer];
button.alpha = 1;
}
- (void)buttonUp {
[self startTimer];
}
- (void)timerFired:(NSTimer *)timer {
[UIView animateWithDuration:0.4
delay:0
options:UIViewAnimationOptionAllowAnimatedContent |
UIViewAnimationOptionAllowUserInteraction |
UIViewAnimationOptionAutoreverse |
UIViewAnimationOptionCurveEaseInOut
animations:^{
button.alpha = MIN_ALPHA;
}
completion:^(BOOL finished) {
button.alpha = 1;
}];
}
I did not use a subclass for the button, but you could easily move it there.
Hope that helps.
Unless you're using a custom Core Animation layer, you probably want your pause and resume methods to look like this (from http://developer.apple.com/library/ios/#qa/qa1673/_index.html):
-(void)pauseLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
layer.speed = 0.0;
layer.timeOffset = pausedTime;
}
-(void)resumeLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer timeOffset];
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause;
}
And pass in button.layer
as the CALayer. If you don't want to pass in the layer, change the references like self.speed
and self.timeOffset
toself.layer.speed
and self.layer.timeOffset
since those properties are only available for the layer, not the button itself.
精彩评论