Pregunta

What is the correct way to use [UIView transitionFromView:toView:...] with layout constraints?

I want to install constraints in the superview constraining toView. I can't do it before the transition call as toView doesn't yet have a superview. (Same for after the call but before the run loop progresses.) Waiting until the completion block to install it means the view will have animated without constraints.

¿Fue útil?

Solución

I'd use the UIViewAnimationOptionShowHideTransitionViews option, which allows both the toView and fromView to be in the view hierarchy before the transition, but shows one and hides the other.

Set toView to be hidden, add it to the superview, and install the constraints before the transition. You can then remove the old view in the completion block. Something like this:

[toView setHidden: YES];
[containerView addSubview: toView];
[containerView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat: @"|[toView]|" options: 0 metrics: nil views: NSDictionaryOfVariableBindings(containerView, toView)]];
[containerView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat: @"V:|[toView]|" options: 0 metrics: nil views: NSDictionaryOfVariableBindings(containerView, toView)]];

[UIView transitionFromView: fromView toView: toView duration: 1.0 options: UIViewAnimationOptionTransitionFlipFromBottom | UIViewAnimationOptionShowHideTransitionViews completion:^(BOOL finished) {
    [fromView removeFromSuperview];
}];

Otros consejos

Adding the constraints after the transition call (but before the run loop progresses) works: my prior test of that was invalid :-(. Sorry for the noise.

    NSArray *priorConstraints = _constraints;
    [UIView transitionFromView:priorView
                        toView:newView
                        ...
                    completion:^(BOOL finished) {
                        [_containerView removeConstraints:priorConstraints];
                        ....
                    }];
    _constraints = [self constrainSubview:newView toBeCongruentWithSuperview:_containerView];


- (NSArray/*[NSLayoutConstraint]*/ *)constrainSubview:(UIView *)subview 
                           toBeCongruentWithSuperview:(UIView *)superview {
    subview.translatesAutoresizingMaskIntoConstraints = NO;
    NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(subview);

    NSArray *constraints = [NSLayoutConstraint 
                            constraintsWithVisualFormat:@"H:-(0)-[subview]-(0)-"
                            options:0
                            metrics:nil
                            views:viewsDictionary];
    constraints = [constraints arrayByAddingObjectsFromArray:
                   [NSLayoutConstraint
                    constraintsWithVisualFormat:@"V:-(0)-[subview]-(0)-"
                    options:0
                    metrics:nil
                    views:viewsDictionary]];
    [superview addConstraints:constraints];
    return constraints;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top