Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I always used to use the following code to make a flip animation between one view and the other:

        [UIView transitionFromView:firstView
                        toView:secondView
                      duration:0.6
                       options:UIViewAnimationOptionTransitionFlipFromLeft
                    completion:^(BOOL finished) {
                        // finish code here
                    }];

This worked fine, giving a natural-looking flip.

But when I used it on the view that was defined on a storyboard using Auto Layout things started getting messy - the views were resized and moved after this animation.

Is there any way to animate this kind of flip by animating constraints?

like image 902
kender Avatar asked Oct 12 '14 20:10

kender


2 Answers

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

like image 89
algal Avatar answered Oct 12 '22 12:10

algal


My best guess will be that animation is performed via animating layer's ~transform, and that transform is applied from the point where anchorPoint position goes. You could try to solve it in two ways:

First: Make sure you position your views via center constraints, ie. align center of the views which are being transformed (not left or top or trailing and stuff). For example, if both views will have, say "horisontaly + vertically" centered in superview this (not sure) could help.

Second: Create a wrapper view, put those views as subviews and disable autolayout for them.

like image 21
MANIAK_dobrii Avatar answered Oct 12 '22 12:10

MANIAK_dobrii