脉冲 UIButton 子类

发布于 2024-11-20 00:32:59 字数 2282 浏览 2 评论 0原文

我正在制作一个简单的 UIButton 子类,它通过使用 UIView 动画更改 alpha 来“脉冲”。我遇到的问题是当用户按下按钮时将 alpha 设置为 1 (100%)。我有代码来暂停和恢复动画,但在调用pauseAnimations之前或之后设置不透明度似乎不起作用。

在 UIView 层上暂停/恢复动画:

-(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;
}

UIButton 子类的代码:

-(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];

    self.oldAlpha = self.alpha;
    self.alpha = self.maximumAlpha;
}

-(void)buttonUp {
    self.alpha = self.oldAlpha;
    [self.layer resumeAnimation];
}

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];

    self.oldAlpha = self.alpha;
    self.alpha = self.maximumAlpha;
}

-(void)buttonUp {
    self.alpha = self.oldAlpha;
    [self.layer resumeAnimation];
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

万水千山粽是情ミ 2024-11-27 00:32:59

尝试从动画选项中删除 UIViewAnimationOptionRepeat。如果您在那里使用它,则意味着动画将无限期地重复。所以停止计时器没有帮助,因为动画将继续重复。

你有没有想过使用NSTimer?这似乎是一种更简单的方法。这就是我所做的:

- (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;
                     }];
}

我没有使用按钮的子类,但您可以轻松地将其移动到那里。

希望有帮助。

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.

我恋#小黄人 2024-11-27 00:32:59

除非您使用自定义核心动画层,否则您可能希望暂停和恢复方法如下所示(来自 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;
}

并传入 button.layer作为CAL层。如果您不想传入图层,请将 self.speedself.timeOffset 等引用更改为 self.layer.speed和 self.layer.timeOffset ,因为这些属性仅适用于图层,而不适用于按钮本身。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文