12

In my game I have a grid of smaller UIViews hosted on my main UIView. Randomly the boxes will turn a different colour, at this point a user can touch them to score a point. When they touch the box I want to show some kind of animation, ideally something similar to the modal horizontal flip segue that XCode offers natively. How can I do this animation without actually transitioning into another UIView?

Chris
  • 26,744
  • 48
  • 193
  • 345

5 Answers5

26

You could simply try and animate the view transform like this (for a vertical flip):

[UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut
                 animations:^(void) {
                     view.transform = CGAffineTransformMakeScale(1, -1);
                 }
                 completion:nil];

or for better control you could have a look into iOS-Flip-Transform.

EDIT:

for the shadow thing, try this:

    view.layer.shadowColor = [UIColor blackColor].CGColor;
    view.layer.shadowOpacity = 0.75;
    view.layer.shadowRadius = 15.0;
    view.layer.shadowOffset = (CGSize){0.0,20.0};

[UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut
                 animations:^(void) {
                     view.transform = CGAffineTransformMakeScale(1, -1);
                 }
                 completion:^(BOOL b) {
    view.layer.shadowColor = [UIColor clearColor].CGColor;
    view.layer.shadowOpacity = 0.0;
    view.layer.shadowRadius = 0.0;
    view.layer.shadowOffset = (CGSize){0.0, 0.0};
                 }];

I hope this works fine for you. You can change the shadow settings as you like. Don't forget to import QuartzCore/QuartzCore.h.

sergio
  • 68,819
  • 11
  • 102
  • 123
  • This is exactly what I was after... How might I change it (for testing purposes) to rotate 90 degrees with drop shadow (as if it pops out of the screen, rotates, then pops back)? – Chris Jan 20 '13 at 20:08
16

UIView provides a method called

+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion

The options include UIViewAnimationOptionTransitionFlipFromLeft and ...Right

danh
  • 62,181
  • 10
  • 95
  • 136
6

For each box that should be flipped you can use a container UIView. Add both sides into this container.

if (side1Visible) {
    UIViewAnimationOptions options = UIViewAnimationOptionBeginFromCurrentState |     
    UIViewAnimationTransitionFlipFromRight;  

    [UIView transitionWithView:containerView  
                  duration:1.0  
                   options:options  
                animations:^{ side1.hidden = YES; side2.hidden = NO; }  
                completion:NULL];  
} else {
    UIViewAnimationOptions options = UIViewAnimationOptionBeginFromCurrentState |     
    UIViewAnimationTransitionFlipFromLeft;  

    [UIView transitionWithView:containerView  
              duration:1.0  
               options:options  
            animations:^{ side1.hidden = NO; side2.hidden = YES; }  
            completion:NULL]; 
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Ilker Baltaci
  • 11,644
  • 6
  • 63
  • 79
1

This is what I ended up with (in Swift 3) based on Ilker Baltaci's answer:

@IBAction func flipViews() {

    // declare variables for transition
    let duration = 0.5
    var animationOptions: UIViewAnimationOptions
    var animations: () -> Void
    var completion: ((Bool) -> Void)?

    if view2.isHidden {
        animationOptions = [.beginFromCurrentState, .transitionFlipFromTop]
        animations = {
            self.view2.isHidden = false
            self.view1.isHidden = true
        }
        completion = { success in
            if success {
                self.updateSomeContentOfView2()
            }
        }
    } else {
        animationOptions = [.beginFromCurrentState, .transitionFlipFromBottom]
        animations = {
            self.view2.isHidden = true
            self.view1.isHidden = false
        }
    }

    UIView.transition(with: containerView,
                      duration: duration,
                      options: animationOptions,
                      animations: animations,
                      completion: completion)
}

My View hierarchy for containerView, view1 & view2 (which are all IBOutlets in my custom ViewController class) is as follows:

  • containerView
    • view1
    • view2
lo2ndii
  • 75
  • 6
0

You can do this with the following code for Swift 3.0:

    UIView.animate(withDuration: 0.5, delay: 0.0, options: .curveEaseInOut, animations: { 
        self.view.transform = CGAffineTransform(scaleX: 1, y: -1)
    }, completion: nil)

Just keep in mind, that this action will occur on your main thread, so the app will be blocked during execution.

If you require a completion handler, there are several options for

CodeBender
  • 35,668
  • 12
  • 125
  • 132