Search code examples
iosuibuttonuicontrol

How to animate transition from one state to another for UIControl/UIButton?


I have a UIButton that changes image on highlight. When transitioning from UIControlStateHighlight to UIControlStateNormal, I want the highlighted image to slowly fade back into the normal image. Is there an easy way to do this?


Solution

  • I ended up subclassing UIButton. Here's the implementation file code. I took some app-specific stuff out, so I haven't tested this exact code, but it should be fine:

    #import "SlowFadeButton.h"
    
    @interface SlowFadeButton ()
    
    @property(strong, nonatomic)UIImageView *glowOverlayImgView; // Used to overlay glowing animal image and fade out
    
    @end
    
    @implementation SlowFadeButton
    
    
    
    -(id)initWithFrame:(CGRect)theFrame mainImg:(UIImage*)theMainImg highlightImg:(UIImage*)theHighlightImg
    {
        if((self = [SlowFadeButton buttonWithType:UIButtonTypeCustom])) {
    
            self.frame = theFrame;
    
            if(!theMainImg) {
                NSLog(@"Problem loading the main image\n");
            }
            else if(!theHighlightImg) {
                NSLog(@"Problem loading the highlight image\n");
            }
    
            [self setImage:theMainImg forState:UIControlStateNormal];
            self.glowOverlayImgView = [[UIImageView alloc] initWithImage:theHighlightImg];
            self.glowOverlayImgView.frame = self.imageView.frame;
            self.glowOverlayImgView.bounds = self.imageView.bounds;
    
            self.adjustsImageWhenHighlighted = NO;
        }
    
        return self;
    }
    
    
    -(void)setHighlighted:(BOOL)highlighted
    {
        // Check if button is going from not highlighted to highlighted
        if(![self isHighlighted] && highlighted) {
            self.glowOverlayImgView.alpha = 1;
            [self addSubview:self.glowOverlayImgView];
        }
        // Check if button is going from highlighted to not highlighted
        else if([self isHighlighted] && !highlighted) {
            [UIView animateWithDuration:1.0f
                             animations:^{
                                 self.glowOverlayImgView.alpha = 0;
                             }
                             completion:NULL];
        }
    
        [super setHighlighted:highlighted];
    }
    
    -(void)setGlowOverlayImgView:(UIImageView *)glowOverlayImgView
    {
        if(glowOverlayImgView != _glowOverlayImgView) {
            _glowOverlayImgView = glowOverlayImgView;
        }
    
        self.glowOverlayImgView.alpha = 0;
    }
    
    @end
    

    You could also just pull the highlighted image from [self imageForState:UIControlStateHighlighted] and use that, it should work the same. The main things are to make sure adjustsImageWhenHighlighted = NO, and then overriding the setHighlighted: method.