views:

1960

answers:

2

I'm dynamically creating UIButton's in my app. When I show the buttons I want to animate them. I can't seem to get the buttons to animate with this code:

UIImage *buttonBackground = [UIImage imageNamed:@"ButtonRed.png"];
for (NSInteger x = 0; x < 4; x++) {

    CGRect btnFrame = CGRectMake(x * (buttonBackground.size.width+2),
                              y * (buttonBackground.size.height + 1),
                              buttonBackground.size.width,
                              buttonBackground.size.height);
    UIButton *gridButton = [[[UIButton alloc] initWithFrame: btnFrame] retain];

    [gridButton setBackgroundImage:buttonBackground forState:UIControlStateNormal];
    [buttonBackground release];

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:.5];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:gridButton cache:YES];

    [self.view addSubview:gridButton];

    [UIView commitAnimations];
    [gridButton release];
}

If I change the "forView:gridButton" to "forView:self.view", then the whole view flips but but not the individual buttons. I just want each individual button to flip.

Thanks for any help.

A: 

The view must be visible before you can call +[UIView setAnimationTransition: forView:cache:] with it as the forView: parameter.

Rearrange such that you add the button to the parent view and then call your animations

rpetrich
I moved the "[self.view addSubview:gridButton];" to before the "beginAnimations" call ...but it still didn't work.
It appears that animations only are allowed on views that are in the window's view hierarchy at the start of the runloop. The simplest way to get around this is to move your animations into an -(void)animate { } method and calling [self performSelector:@selector(animate) withObject:nil afterDelay:0.0f]; in your viewDidShow: method
rpetrich
A: 

Thanks so much for your suggestions, rpetrich. It got me thinking in the right direction.

It seemed as though the animations would not run inside the for loop for each individual button. I tried to wrap the whole FOR loop in a beginAnimations call, but that didn't work either.

I wasn't terribly familiar with performSelector command that rpetrich suggested, but I figured I could use a timer.

I was finally able to animate the buttons by setting all the dynamically created buttons to be hidden at first in the FOR loop and then outside the FOR loop I created a timer that would unhide them while doing the animation.

Here's the code changes I made:

UIImage *buttonBackground = [UIImage imageNamed:@"ButtonRed.png"];
for (NSInteger x = 0; x < 4; x++) {

    CGRect btnFrame = CGRectMake(x * (buttonBackground.size.width+2),
                                 y * (buttonBackground.size.height + 1),
                                 buttonBackground.size.width,
                                 buttonBackground.size.height);
    UIButton *gridButton = [[[UIButton alloc] initWithFrame: btnFrame] retain];

    [gridButton setBackgroundImage:buttonBackground forState:UIControlStateNormal];
    [buttonBackground release];

    // ****** I took out all animation code ******
    [self.view addSubview:gridButton];
    gridButton.hidden = YES; // <----------- ****** new code ******

    [gridButton release];
}

// **** the following code was added just outside the FOR loop to create timer that will animate buttons as they're un-hidden.
// NSTimer gridTimer is created in the header file.
gridTimer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(showGrid) userInfo:nil repeats:NO];

Here's the new method I call with the timer:

-(void) showGrid{
    for (UIButton *obj in self.view.subviews) {
     if ([obj isMemberOfClass:[UIButton class]]) {
      [UIView beginAnimations:nil context:NULL];
      [UIView setAnimationDuration:1];
      [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:obj cache:YES];//~~self.view cache:YES];    
      obj.hidden = NO;
      [UIView commitAnimations];
     }
    }
    [gridTimer invalidate];
}
Syler