Uiview Vertical Flip Animation

UIView vertical flip animation

As of iOS 5.0, there's no need to write your own Core Animation transformation to do vertical flips. Just use UIKit's UIViewAnimationOptionTransitionFlipFromTop and UIViewAnimationOptionTransitionFlipFromBottom transitions, and all this stuff becomes a single method call.

These behave analagously to UIViewAnimationOptionTransitionFlipFromLeft and UIViewAnimationOptionTransitionFlipFromRight (which have been around since iOS 2.0).

Example usage:

[UIView transitionFromView:viewToReplace
toView:replacementView
duration:1
options:UIViewAnimationOptionTransitionFlipFromBottom
completion:nil];

The above code will vertically flip the superview of viewToReplace. At the halfway point in the animation, at the instant when the superview is perpendicular to the screen and thus invisible, viewToReplace gets replaced by replacementView.

It's that easy.

UIView flip animation

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.

How to make flip animations from one UIView to another when using Auto Layout?

Auto Layout can only be used to position and resize views. It cannot be used to produce the kind of Core Animation transform needed to produce the flip transition effect. So the short exact answer is no, there is no way to animate this kind of flip by animating constraints.

Using the show/hide transition option

However, there is a simple way to modify the code you are already using so that it is consistent with Auto Layout. The way to do it is (1) to add both your firstView and secondView to your view hierarchy before you order the animation, (2) to ensure that you've added Auto Layout constraints that define the layout of both those views, and (3) to add an option to the animation so that you are only showing/hiding the two views, rather than tearing down and setting up a new view hierarchy.

In other words you want something like:

        // assert: secondView added to view hierarchy
// assert: secondView.hidden == true
// assert: secondView has correct constraints
[UIView transitionFromView:firstView
toView:secondView
duration:0.6
options:UIViewAnimationOptionTransitionFlipFromLeft | UIViewAnimationOptionShowHideTransitionViews
completion:nil];

Why is this what's needed? The reason is that, without the UIViewAnimationOptionShowHideTransitionViews option, the method transitionFromView:toView:duration:options:completion: will actually manipulate the view hierarchy and add the new destination view. If Auto Layout is engaged, then it won't be laid out correctly since it won't have constraints.

You can see an example project showing this approach working here: https://github.com/algal/AutoLayoutFlipDemo

Using view hierarchy manipulation

Alternatively, you can also use your existing call to transitionFromView:toView:duration:options:completion:. But if you're not going to just show a destination view that already had constraints in place, then you need to use the completion block to add those constraints, as follows:

    [UIView transitionFromView:firstView
toView:secondView
duration:0.6
options:UIViewAnimationOptionTransitionFlipFromLeft
completion:^(BOOL finished) {
[self.view addConstraint:[NSLayoutConstraint
constraintWithItem:secondView
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1 constant:0]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:secondView
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterY
multiplier:1 constant:0]];
}];

A working example of this approach is here: https://github.com/algal/AutoLayoutFlipDemo2

Interactive UIView flip transition

I ended up writing it myself. The code is pretty long, so here's a link to the full program on GitHub. Here are the key parts:

Everything is encapsulated in an InteractiveFlipAnimator object that takes a front view (v1) and a back view (v2). Each view also gets a black cover that functions as a shadow to add that darkening effect when the view turns in perspective.

Here is the panning function:

/// Add a `UIPanGestureRecognizer` to the main view that contains the card and pass it onto this function.
@objc func pan(_ gesture: UIPanGestureRecognizer) {
guard let view = gesture.view else { return }
if isAnimating { return }

let translation = gesture.translation(in: view)
let x = translation.x
let angle = startAngle + CGFloat.pi * x / view.frame.width

// If the angle is outside [-pi, 0], then do not rotate the view and count it as touchesEnded. This works because the full width is the screen width.
if angle < -CGFloat.pi || angle > 0 {
if gesture.state != .began && gesture.state != .changed {
finishedPanning(angle: angle, velocity: gesture.velocity(in: view))
}
return
}

var transform = CATransform3DIdentity
// Perspective transform
transform.m34 = 1 / -500
// y rotation transform
transform = CATransform3DRotate(transform, angle, 0, 1, 0)
self.v1.layer.transform = transform
self.v2.layer.transform = transform

// Set the shadow
if startAngle == 0 {
self.v1Cover.alpha = 1 - abs(x / view.frame.width)
self.v2Cover.alpha = abs(x / view.frame.width)
} else {
self.v1Cover.alpha = abs(x / view.frame.width)
self.v2Cover.alpha = 1 - abs(x / view.frame.width)
}

// Set which view is on top. This flip happens when it looks like the two views make a vertical line.
if abs(angle) < CGFloat.pi / 2 {
// Flipping point
v1.layer.zPosition = 0
v2.layer.zPosition = 1
} else {
v1.layer.zPosition = 1
v2.layer.zPosition = 0
}

// Save state
if gesture.state != .began && gesture.state != .changed {
finishedPanning(angle: angle, velocity: gesture.velocity(in: view))
}
}

The code to finish panning is very similar, but it is also much longer. To see it all come together, visit the GitHub link above.

How to flip a UIView around the x-axis while simultaneously switching subviews

This turned out to be way simpler than I thought and I didn't have to use any CoreAnimation libraries to achieve the effect. Thanks to @Aaron Hayman for the clue. I used transitionWithView:duration:options:animations:completion

My implementation inside the container view:

    [UIView transitionWithView:self 
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromBottom
animations: ^{
[self.backView removeFromSuperview];
[self addSubview:self.frontView];
}
completion:NULL];

The trick was the UIViewAnimationOptionTransitionFlipFromBottom option. Incidentally, Apple has this exact bit of code in their documentation. You can also add other animations to the block like resizing and moving.

How can I flip between two UIView?

You can use the UIView class method +transitionFromView:toView:duration:options:completion: to accomplish this. Both your text views need to be descendants of a common superview. Use the option UIViewAnimationOptionTransitionFlipFromLeft (or ...FromRight) to get a horizontal flip.



Related Topics



Leave a reply



Submit