donkey
donkey

Reputation: 1448

Perform custom animation with custom frame images

I'm using storyboard. I have a 2 UIViewControler: view1 and view2. When pressing any of 6 button on view1 a segue is performed and therefore this method is called: prepareForSegue:. Now I would like to animate the view1 before it performs the segue with 6 custom images called navExitFrame1, navExitFrame2... and then show a default animation set in the storyboard under Modal>flip horizontal.

EDIT:

I am now using this code:

    void (^animationBlock)() = ^{

        NSArray *images = @[[UIImage imageNamed:@"navExitFrame1.png"],
                            [UIImage imageNamed:@"navExitFrame2.png"],
                            [UIImage imageNamed:@"navExitFrame3.png"],
                            [UIImage imageNamed:@"navExitFrame4.png"],
                            [UIImage imageNamed:@"navExitFrame5.png"],
                            [UIImage imageNamed:@"navExitFrame6.png"]];

        UIImage *myimage = [UIImage imageNamed:@"profile.png"];

        [profileButton.imageView setImage:myimage];

        [self.view bringSubviewToFront:imageView];
        imageView.hidden = NO;

        NSUInteger imagesCount = [images count];

        for(NSUInteger i=0; i<imagesCount; i++) {

            [UIView addKeyframeWithRelativeStartTime:i/(CGFloat)imagesCount
                                    relativeDuration:1/(CGFloat)imagesCount
                                          animations:^{

                                              imageView.image = images[i];

                                          }];
        }
    };

    [UIView animateKeyframesWithDuration:1 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeDiscrete animations:animationBlock completion:^(BOOL finished) {

        if (sender == feelingsButton) {

            NSString *save = @"feelings";
            [[NSUserDefaults standardUserDefaults] setObject:save forKey:@"segueID"];

        } else if (sender == placesButton) {

            NSString *save = @"places";
            [[NSUserDefaults standardUserDefaults] setObject:save forKey:@"segueID"];

        }else if (sender == peopleButton) {

            NSString *save = @"people";
            [[NSUserDefaults standardUserDefaults] setObject:save forKey:@"segueID"];

        }else if (sender == settingsButton) {

            NSString *save = @"settings";
            [[NSUserDefaults standardUserDefaults] setObject:save forKey:@"segueID"];

        }else if (sender == profileButton) {

            NSString *save = @"profile";
            [[NSUserDefaults standardUserDefaults] setObject:save forKey:@"segueID"];

        }else if (sender == mainWebView || sender == mainWebView.gestureRecognizers) {

            NSString *save = @"newsfeed";
            [[NSUserDefaults standardUserDefaults] setObject:save forKey:@"segueID"];
        }

       [self performSegueWithIdentifier:@"ContentVWS" sender:nil];

    }];
}

What is happening here is that the animation is taking place but in the space of a MICROsecond, I tried modifying the value of the Duration in

animateKeyframesWithDuration:1

but nothing changes. Also after putting a breakpoint in the for loop I realise that no images are shown except for the last one but when I go in the build phases the images are listed as copy resource bundle and the image names are spelled correctly possibly that is why it is taking place in such a short period of time. Also maybe the values of

UIView animateKeyframesWithDuration:1 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeDiscrete animations:animationBlock completion:^(BOOL finished) {

are incorrect, I NSloged them in the completion but only the variable i is correct and imagesCount is correct too but when I do i/(CGFloat)imagesCount is seems to always be returning 0 for some reason. Does that have anything to do with it?

Upvotes: 3

Views: 1441

Answers (1)

tjboneman
tjboneman

Reputation: 668

Ok, it seems like the new keyframe animation method in iOS7 doesn't want to play nicely with changes in uiimage on an image view, so we will have to use a CAKeyframe animation instead: This answer comes in part from here: http://stackoverflow.com/questions/16025769/how-do-i-simultaneously-animate-a-uiimageviews-image-and-the-uiimageview-itself

-(IBAction)animateImagesThenPushView:(id)sender{

    NSArray *images = @[[UIImage imageNamed:@"navExitFrame1.png"],
                        [UIImage imageNamed:@"navExitFrame2.png"],
                        [UIImage imageNamed:@"navExitFrame3.png"],
                        [UIImage imageNamed:@"navExitFrame4.png"],
                        [UIImage imageNamed:@"navExitFrame5.png"],
                        [UIImage imageNamed:@"navExitFrame6.png"]];

    NSMutableArray *keyTimes = [NSMutableArray arrayWithCapacity:images.count];
    for (int i = 0; i<images.count; i++) {
        keyTimes[i] = @(0.0 + (i+1)*(1.0/images.count));
    }

    CAKeyframeAnimation *imageAnimation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
    imageAnimation.calculationMode = kCAAnimationDiscrete; // or maybe kCAAnimationPaced
    imageAnimation.duration = .5;
    imageAnimation.keyTimes = keyTimes;
    imageAnimation.repeatCount = 0;
    // the following method will need to be implemented to cast your UIImage array to CGImages
    imageAnimation.values = [self animationCGImagesArrayFromImageArray:images];
    imageAnimation.delegate = self;
    [self.imageView.layer addAnimation:imageAnimation forKey:@"content"];

}

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
    self.imageView.image = [UIImage imageNamed:@"navExitFrame6.png"];
    // put your segue logic here to push the next view
}

-(NSArray*)animationCGImagesArrayFromImageArray:(NSArray*)imageArray {
    NSMutableArray *array = [NSMutableArray arrayWithCapacity:imageArray.count];
    for (UIImage *image in imageArray) {
        [array addObject:(id)[image CGImage]];
    }
    return [NSArray arrayWithArray:array];
}

Upvotes: 3

Related Questions