How to flash a button on UI thread?

淺唱寂寞╮ 提交于 2019-12-08 06:25:31

I would recommend using Core Animation. Try something like this:

-(void) flash{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3f];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];

    if( emergency ){       
        // Start flashing
        [UIView setAnimationRepeatCount:1000];
        [UIView setAnimationRepeatAutoreverses:YES];

        [btn setAlpha:0.0f];        
    }else{
        // Stop flashing
        [UIView setAnimationBeginsFromCurrentState:YES];
        [UIView setAnimationRepeatCount:1];

        [btn setAlpha:1.0f];        
    }
    emergency = !emergency;
    [UIView commitAnimations];
}

Where btn is declared as

@property(nonatomic, retain) IBOutlet UIButton *btn;

and emergency is a simple BOOL variable.

Call flash to start and to stop the animation.

In this example we animate the alpha attribute for simplicity, but you can do the same with the button backcolor, as Sam said in his answer, or whatever attribute you like.

Hope it helps.

UPDATE:

Regarding making the transition between two images, try calling imageFlash instead of flash:

-(void) imageFlash{

    CABasicAnimation *imageAnimation = [CABasicAnimation animationWithKeyPath:@"contents"];
    [btn setImage:normalState forState:UIControlStateNormal];

    if( emergency ){        
        imageAnimation.duration = 0.5f;
        imageAnimation.repeatCount = 1000;
    }else{
        imageAnimation.repeatCount = 1;
    }

    imageAnimation.fromValue = (id)normalState.CGImage;
    imageAnimation.toValue = (id)emergencyState.CGImage;    
    [btn.imageView.layer addAnimation:imageAnimation forKey:@"animateContents"];    
    [btn setImage:normalState forState:UIControlStateNormal]; // Depending on what image you want after the animation.

    emergency = !emergency;
}

Where normalState and emergencyState are the images you want to use:

Declared as:

UIImage *normalState;
UIImage *emergencyState;

Assigning the images:

normalState = [UIImage imageNamed:@"normal.png"];
emergencyState = [UIImage imageNamed:@"alert.png"];

Good luck!

While this feels like a job for CoreAnimation (perhaps animating the backgroundColor of a custom UIControl) you could accomplish this with an NSTimer running in the appropriate run loop mode.

e.x.

NSTimer *timer = [NSTimer timerWithTimeInterval:0.8f target:self selector:@selector(flicker:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

and when you want to stop animation:

[timer invalidate], timer = nil;
button.selected = NO;

By adding the timer to all NSRunLoopCommonModes, you not only add it to the default run loop mode but the mode it is in while user interaction is being continuously processed (UITrackingRunLoopMode.)

Apple's docs give a more thorough explanation of run loop modes and run loops in general.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!