Search code examples
iosuibuttonnstimer

Fade Button in and Out While being clicked/not clicked


I am trying to get a button to move to random locations inside my view. However, the dot only moves at random when it is pressed. I also want it to fade to a different location if it is not pressed. I used CGRect because I need the dot to stay within the bounds of a specific view.

-(IBAction)randomRed:(id)sender
{
    [self redDot];

    CGRect senderFrame = [sender frame];
    CGRect superBounds = [[sender superview ] bounds];
    senderFrame.origin.x = (superBounds.size.width - senderFrame.size.width) * drand48();
    senderFrame.origin.y = (superBounds.size.height - senderFrame.size.height) * drand48();
    [sender setFrame:senderFrame];

    counter = counter - 5;
    scoreLabel.text = [NSString stringWithFormat:@"Points %i", counter];

    NSString *path = [[NSBundle mainBundle] pathForResource:@"Tapadot Red Dot Buzzer Short" ofType:@"mp3"];
    sound = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
    sound.numberOfLoops = 1;
    [sound play];

    [self subtractOne];
    [self performSelector:@selector(showRedDot) withObject:nil afterDelay:1.0];
}

-(void)startRedDot
{
    if (counter ==0)
        redDot = [NSTimer scheduledTimerWithTimeInterval:4.0
                                                  target:self
                                                selector:@selector(showRedDot)
                                                userInfo:nil
                                                 repeats:YES];
}

-(void)showRedDot
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:1.0];
    [redButton setAlpha:1];
    [UIView commitAnimations];

    [self performSelector:@selector(redDot) withObject:nil afterDelay:1.0];
}

-(void)redDot
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.5];
    [redButton setAlpha:0];
    [UIView commitAnimations];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self setUpGame];
    [self sizing];
}

Solution

  • Currently your random positioning code is only called when the button is pressed.

    To get it to move Independent of button presses we should put it in its own method, which can invoke itself after a set duration.

    First we need to get a reference to the instance of the button you want to move so we can manipulate it.

    Then lets separate the movement code into its own method.

    - (void) moveButtonRandomly {
        CGSize limits;
        CGPoint newPosition;
    
        // Get limits
        limits.width = self.view.frame.size.width - button.frame.size.width;
        limits.height = self.view.frame.size.height - button.frame.size.height;
    
        // Calculate new Position
        newPosition = (CGPoint){ limits.width * drand48(), limits.height * drand48() };
    
        // Set new frame
        button.frame = (CGRect){ newPosition, button.frame.size };
    }
    

    Change your startRedDot to this, which will construct, and start the timer.

    - (void) startRedDot {
        redDotTimer = [NSTimer scheduledTimerWithTimeInterval:4.0
                                                  target:self
                                                selector:@selector(moveButtonRandomly)
                                                userInfo:nil
                                                 repeats:YES];
        [redDotTimer fire];
    }
    

    The animation is rather simple to add just create a new method which invokes two animations; One which fades out the button with a completion that moves the button, and fires off the next animation to fade it back in.

    - (void) moveButtonWithAnimation {
        CGFloat fadeDurration;
        if ( !button )
            return; // only invoke the button if it exists
        fadeDurration = 0.4;
    
        //Fade Out
        [UIView animateWithDuration: fadeDurration animations:^{
            button.alpha = 0.0f;
    
        } completion:^(BOOL finished) {
            // Move the button while it is not visible
            [self moveButtonRandomly];
    
            // Fade in
            [UIView animateWithDuration: fadeDurration animations:^{
                button.alpha = 1.0f;
            }];
        }];
    }
    

    Finally Edit the timers selector to be the animation method.

    - (void) startRedDot {
        redDotTimer = [NSTimer scheduledTimerWithTimeInterval:4.0
                                                  target:self
                                                selector:@selector(moveButtonWithAnimation)
                                                userInfo:nil
                                                 repeats:YES];
        [redDotTimer fire];
    }